2. 변수

1. 변수(variable)와 상수

1.1 변수란?

단 하나의 값을 저장할 수 있는 메모리 공간

1.2 변수의 선언과 초기화

int(변수타입) age(변수이름);

메모리의 빈 공간에 ‘변수타입’에 알맞은 크기의 저장공간이 확보되고 앞이로 이 저장공간은 ‘변수이름’을 통해 사용 가능

변수의 초기화

변수를 사용하기 전에 처음으로 값을 저장하는 것

int a, b; // 변수의 타입이 같은 경우 콤마’,’를 구분자로 한 줄에 선언 가능

int x = 0, y = 0;

두 변수의 값 교환하기

int x = 10;

int y = 20;

int tmp; // x값을 임시로 저장할 변수를 이용

tmp = x;

x = y;

y = tmp;

1.3 변수의 명명규칙

식별자(identifier)

‘변수의 이름’처럼 프로그래밍에서 사용하는 모든 이름 식별자를 만들 때 규칙 4

1. 대소문자가 구분되며 길이에 제한이 없다.
2. 예약어를 사용해서는 안 된다.
3. 숫자로 시작해서는 안 된다.
4. 특수문자는 ‘_’와 ‘$’만을 허용한다.

예약어

키워드(keyword) 또는 ‘리져브드 위드(reserved word)’라고 하며 프로그래밍 언어의 구문에 사용

  • 자주 사용되는 예약어
abstract default if package this
assert do goto private throw
boolean double implements protected throws
break else import public transient
byte enum instanceof return true
case extends int short try
catch false interface static void
char final long strict volatile
class finally native super while
const float new switch continue
for null synchronized

변수 명명 권장 사항

  1. 클래스 이름의 첫 글자는 항상 대문자로 한다. 변수와 메서드의 이름의 첫 글자는 항상 소문자로 한다.

  2. 여러 단어로 이루어진 이름은 단어의 첫 글자를 대문자로 한다. ex) lastIndexOf

  3. 상수의 이름은 모두 대문자로 한다. 여러 단어로 이루어진 경우 ‘_’로 구분한다. ex) MAX_NUMBER

2. 변수의 타입

기본형(primitive type)

  • 실제 값(data)을 저장

참조형(reference type)

  • 어떤 값이 저장되어 있는 주소(memory address)를 값으로 저장
  • 참조변수를 선언하는 방법: 클래스 이름 변수이름; // 변수의 타입이 클래스 이름인 것들은 모두 참조변수이다.
  • 참조형 변수를 구분할 때 ‘타입(type)’이라는 용어를 사용하며 기본형 변수는 ‘자료형(data type)’ 이라는 용어를 사용.
  • ‘타입(type)’이 ‘자료형(data type)’을 포함하는 보다 넓은 의미

2.1 기본형(primitive type)

모두 8개의 타입이 있으며 크게 논리형, 문자형, 정수형, 실수형으로 구분

논리형(boolean)

  • true와 false 중 하나를 값으로 갖으며, 조건식과 논리적 계산에 사용
  • 타입의 크기: boolean=1byte
  • 다른 기본형과의 연산이 불가능

문자형(char)

  • 문자를 저장하는데 사용되며, 변수 당 하나의 문자만 저장 가능
  • 타입의 크기: char=2byte

정수형(byte, short, int, long)

  • 정수 값을 저장하는 데 사용하며, 주로 int와 long이 사용
  • 타입의 크기: byte=1byte, short=2byte, int=4byte, double=8byte
  • 값의 범위: -2ⁿ⁻¹ ~ 2ⁿ⁻¹ -1(n: bit수)
  • int타입의 변수는 대략 10자리 수, long타입의 변수는 19자리 수
  • byte는 이진 데이터를 다루는데 주로 사용
  • short는 C언어와의 호환을 위해서 추가

실수형(float, double)

  • 실수를 저장하는데 사용되며, 주로 double 사용
  • 타입의 크기: float=4byte, double=8byte
  • 정수형과 저장형식이 달라서 같은 크기라도 훨씬 큰 값을 표현할 수 있으나 오차가 발생할 수 있는 단점이 있음
  • 정밀도에 따라 오차의 범위가 달라짐
  • 정밀도: float(7자리), double(15자리)

2.2 상수와 리터럴(constant & literal)

상수

  • 변수와 마찬가지로 '값을 저장할 수 있는 공간'
  • 변수와 달리 한번 값을 저장하면 다른 값으로 변경할 수 없음
  • 변수와 선언하는 법은 동일하며, 타입 앞에 'final'키워드를 붙임
  • 선언과 동시에 초기화 해야하며, 그 후 부터는 상수의 값 변경 불가
  • 이름은 모두 대무자로 하는 것이 관례이며, 여러 단어로 이루어진 경우 '_'로 구분

리터럴(literal)

  • 12, 123, 'A'와 같은 기존 '상수'의 다른 이름

상수가 필요한 이유

  • 리터럴에 '의미있는 이름'을 붙여서 코드의 이해와 수정을 도움

리터럴의 타입과 접미사

  • 논리형: false, true / 접미사 없음

  • 정수형: 123,0b0101, 077, 0xFF, 100L / L

    • long타입의 리터럴에 접미사 'l' 또는 'L'을 붙임 접미사가 없으면 int타입
      • long big = 100_000_000_000L; // 100000000000L;
    • byte와 short타입의 변수에 값을 저장할 때는 int타입의 리터럴 사용
    • 10진수 외에 2, 8, 16진수로 표현된 리터럴을 변수에 저장 가능
      • 16진수: 접두사 '0x' or '0X'
      • 8진수: 접두사 '0'
      • 2진수: 접두사 '0b'or '0B'(JDK 1.7부터) JDK 1.7부터 정수형 리터럴 중간에 구분자 '_'를 넣을 수 있어서 큰 숫자 읽을 때 용이
  • 실수형: 3.14, 3.0e8, 1.4f, 0x1.0p-1 / f, d

    • float타입에 접미사 'f' or 'F'
    • double타입에 접미사 'd' or 'D'(실수형의 기본 자료형으로 생략 가능)
    • 리터럴에 소수점이나 10의 제곱을 나타내는 기호 E 또는 e, 그리고 접미사 f, F, d, D 포함시에 실수형 리터럴로 간주
    • 16진 지수 형태 표현: p or P(2의 제곱을 의미)
      • 왼쪽에 16진수를 적고 오른쪽에 지수를 10진수 정수로 적음: 0x1p1 = (116^0) 2^1 = 1.0 * 2 = 2.0
  • 문자형: 'A', '1' / 접미사 없음

  • 문자열: "ABC" / 접미사 없음

타입의 불일치

타입이 달라도 저장 범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용

  • long l = 123; // long > int

문자 리터럴과 문자열 리터럴

문자 리터럴

  • 작은 따옴표로 문자 하나를 감싼 것
  • char변수는 단 하나의 문자만 저장 가능

char ch = ''; // error

char ch = ' '; // ok, 공백문자로 초기화

문자열 리터럴

  • 큰 따옴표로 감싼 것
  • "" 안에 아무런 문자도 넣지 않는 것 허용

String name = new String("Java");

String name = "Ja" + "va";

  • +은 피연산자 중 어느 한쪽이 String이면 나머지 한쪽을 먼저 String으로 변환 후 결합

String str = name + 8.0;

2.3 형식화된 출력 - printf()

'지시자(specifier)'를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력

  • 출력 후 줄바꿈 없음(줄바꿈 지시자: %n)

자주 사용되는 printf의 지시자

%b boolean

%d 10진수(decimal integer)

int finger = 10;

printf("finger=[%5d]%n", finger); // finger=[ 10]

printf("finger=[%-5d]%n", finger); // finger=[10 ]

printf("finger=[%05d]%n", finger); // finger=[00010]

char c = 'A';

printf("c=%c, %d%n", c, (int)c); // 형변환이 꼭 필요

%o 8진수

int octNum = 010;

printf("octNum=%o, %#o%n", octNum); // octNum=10, 010

%x, %X 16진수

int hexNum = 0x10;

printf("hexNum=%x, %#x%n", hexNum); // hexNum=10, 0x10

%f 10진수(decimal float)

소수점 이하 6자리까지만 출력하며 소수점 이하 7자리에서 반올림 (1.23456789 = 1.234568)

  • 전체 자리수와 소수점 이하 자리수 지정

%전체자리.소수점이하자리f(소수점도 한자리 차지)

%e, %E 지수형태표현

%c 문자

%s 문자열

int binNum = ob10; // 2진수 10 printf("binNum=%s%n", Integer.toBinaryString(binNum)); // binNum=10

  • 숫자를 추가하면 원하는 만큼의 출력공간을 확보하거나 문자열의 일부만 출력 가능

2.4 화면에서 입력받기 - Scanner

import java.util.*; // Scanner클래스를 사용하기 위해 추가

Scanner scanner = new Scanner(System.in);

String input = scanner.nextLine(); // 입력대기 상태에 있다가 입력 후 엔터키를 누르면 입력한 내용이 문자열로 반환

int num = Integer.parseInt(input); // 문자열을 int타입의 정수로 변환 or int num = scanner.nextInt(); // 정수를 입력 받음

3. 진법

3.1 10진법과 2진법

10진수 2진수
0 0
1 1
2 10 (자리올림)
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
10 (자리올림) 1010

3.2 비트(bit)와 바이트(byte)

비트(bit, binay digit)

  • 한 자리의 2진수로 컴퓨터가 값을 저장할 수 있는 최소단위 바이트(byte)
  • 1비트 8개를 묶어서 데이터의 기본 단위로 사용 워드(word)
  • CPU가 한번에 처리할 수 있는 데이터의 크기
  • CPU의 성능에 따라 32비트 CPU에서 1워드는 32비트(4바이트) / 64비트 CPU에서는 64비트(8바이트)

n비트로 표현할 수 있는 10진수

  • 값의 개수: 2ⁿ
  • 값의 범위: 0 ~ 2ⁿ-1

3.3 8진법과 16진법

8진법: 0 ~ 7 16진법: 0 ~ 9, A ~ F

2진수를 8진수, 16진수로 변환

8진수 = 2³

  • 2진수를 뒤에서부터 3자리씩 끊어서 그에 해당하는 8진수로 변환

16진수 = 2⁴

  • 2진수를 뒤에서부터 4자리씩 끊어서 그에 해당하는 16진수로 변환 -

3.4 정수의 진법 변환

(수학시간인줄) %2 를 반복해서 나머지를 순서대로 이으면 2진법 숫자로 바뀜

3.5 실수으 진법 변환

10진 소수점수를 2진 소수점수로 변환하는 방법 3.4 와 반대다. 1) 10진 소수에 2를 곱한다 2) 위의 결과에서 소수부만 가져다가 다시 2를 곱한다 3) 1) 2) 과정을 소수부가 0이 될때까지 반복한다. 곱한 결과의 정수부만 순서대로 나열하면 2진 소수ㅈ값이 나온다ㅏ.

3.6 음수의 2진 표현 - 2의 보수법

왼쪽의 첫 번째 비트가 0인면 양수, 1이면 음수다. 1001 을 -1로 해석하는 방식이 있고, 1001을 -7로 해석하는 방식이 있다. 1001을 -7로 해석하는 방식을 2의 보수법이라고 한다. 양수와 음수를 더했을 때 2진수로 같은 결과를 얻으므로 부호를 신경쓰지 않고 덧셈할 수 있게 된다. 그리고 2진수가 증가할 때 10진 음수가 감소한다는모순도 없어진다.

2으이 보수를 구하는 방법은

  • 2의 보수 = 1의 보수 + 1

4. 기본형

4.1 논리형 - boolean true, false 중 하나를 저장할 수 있으며기본값은 fals 대문자 True, False는 에러다

4.2 문자형 - char

char ch = 'A';

위의 문장은 변수에 문자가 저장되는 것 같지만, 사실은 문자가 아닌 '문자의 유니코드 정수'가 저장된다.

char ch = 'A';
char ch = 65;
// 위 둘은 동일한 결과
  • 아스키 아스키는 128개 문자 집합 7비트 부호
  • 확장 아스키와 한글 확장 아스키에 추가된 128개의문자는 여러 국가와 기업에서 서로의 필요에 따라 다르게 정의해서 사용한다. 그 중에서 대표적인것이 ISO-8859-1이다. 이 확장 아스키 버전은 ISO Latin 1 이라고도 하는데 서유럽에서 일반적으로 사용하는 문자들을 포함하고 있다.

한글을 표현하는 방법은 조합형과 완성형이 있는데, 조합형은 초성 중성 종성을 조합하는 방식이고 완성형은 확장 아스키의 일부 영역에 해당하는 두 문자코드를 조합해서 한글을 표현한다. 요즘은 완성형에 없는 잘 안쓰는 8822글자를 추가한 확장 완성형 CP 949이 사용되는데, 이것이 바로 한글 윈도우에서 사용하는 문자 인코딩이다.

  • 코드 페이지 IBM에서 자사의 PC에 확장 아스키를 도입하기 시작할 때, 국가에 따라 어려 버전의 확장 아스키가 필요했다. IBM은 이를 Code Page라 했다. 한글 윈도우는 CP 949, 영문 윈도우는 CP 437을 사용한다.

  • 유니코드 예전엔 같은 지역 내에서만 문서교환이 주를 이뤘지만,. 인터넷 시대에서 여러 나라에서 문서를 주고받을 때 이를 통합하려는 노력으로 유니코드가 생겼다. 유니코드 인코딩에는 UTF-8, UTF-16, UTF-32 등 여러가지 종류가 있는데, 자바에서는 UTF-16을 사용한다. UTF-16은 모든 문자를 2바이트로 동일하게 표현하는 반면, UTF-8은 영어 숫자는 1바이트, 한글은 3바이트를 사용한 가변 방식으로 표현한다. 인터넷에선 요즘 UTF-8 문서가 빠르게 늘어나고 있다.

4.3 정수형 정수형은 byte, short보다 int를 사용해라 JVM의 피연산자 스택이 피연산자를 4바이트 단위로 저장하기 때문에 4바이트보다 작은 자료형의 값을 계산할 때는 4바이트로 변환하여 연산이 수행된다. 그래서 오히려 int를 사용하는 것이 더 효율적이다.

정수형 변수를 선언할 때는 int 타입으로 하고 int의 범위(약 20억)을 넘어서는 수를 다뤄야 할 때는 long을 사용하면 된다. 그리고 byte, short는 성능보다 저장공간 절약할 때 쓰도록 하자.

  • 오버플로우가 발생한다고 에러가 발생하지는 않는다. 그러니 적절한 변수형을 사용하자.

4.4 실수형

float의 정밀도는 7자리 double의 정밀도는 15자리

5. 형변환

5.1 형변환 캐스팅이란?

  • 형변환이란 변수 또는 상수의 타입을 다른 타입으로 변환하는 것

5.2 형변환 방법

  • (타입) 피연산자

5.3 정수형간의 형변환

큰 타입에서 작은 타입으로 변환시 값 손실이 발생할 수 있다.

5.4 실수형간의 형변환

  • float 타입의 범위를 넘는 값을 float으로 변환하면 무한대 또는 0을 결과로 얻는다.

    5.5 정수형과 실수형 간의 형변환

5.6 자동 형변환

서로 다른 타입간의 대입이나 연산을 할 때 형변환으로 타입을 일치시키는 것이 원칙이지만 생략도 가능하다.

1. boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능하다.
2. 기본형과 참조형은 서로 형변환할 수 없다.
3. 서로 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있다.