타입이 정해지는 타이밍에 따라 언어를 다음과 같이 구분 가능하다.
Java의 타입 종류에는 기본형(Primitive Type)과 참조형(Reference Type)이 있다.
기본형에는 byte, short, int, long, char, float, dobule, boolean 타입이 존재한다.
각 타입의 메모리 사이즈는 다음과 같다.
타입 | 설명 | 사이즈 | 값의 범위 |
---|---|---|---|
byte | 부호 있는 정수값 | 8bit | -128 ~ 127 |
short | 부호 있는 정수값 | 16bit | -32768 ~ 32767 |
int | 부호 있는 정수값 | 32bit | -231 ~ 231-1 |
long | 부호 있는 정수값 | 64bit | -263 ~ 263-1 |
char | 유니코드 문자 | 16bit | '\u0000' ~ '\uffff' / 0 ~ 65535 |
float | 부동소수점수 | 32bit | 2-149 ~ (2-2-23)*2127 (양수 범위, 부호를 마이너스로 하면 음수 범위) |
double | 부동소수점수 | 64bit | 2-1074 ~ (2-2-52)*21023 |
boolean | 논리값 | 1bit | true / false |
int number = 10;
위에서 number 변수에 '10'이라는 값을 대입하고 있다.
이 대입값을 구체적으로 표현한 표기를 리터럴이라고 부른다.
기본형 리터럴에는 다음과 같은 것이 있다.
int num10 = 10; //10진수 10
int num8 = 012; //8진수 10
int num16 = 0xa; // 16진수 10
int num2 = 0b1010; // 2진수 10
long longNum = 10L;
float floatNum = 3.14f;
double doubleNum = 3.14;
boolean bool = true;
char c = 'A';
타입끼리 호환성이 있으면 자동으로 변환된다.
ex) short 변수를 int 변수에 담는 확장 변환
호환성이 없는 경우는 자동으로 변환되지 않아 컴파일 에러가 뜬다.
ex) int 변수를 short 변수에 담는 축소 변환
ex) int 변수를 char 변수에 담는 경우
이 때, 타입을 명시적으로 지정해 타입을 변환할 수 있으며, 이를 캐스트Cast라고 부른다.
단, 변환 전의 타입 범위가 변환 후의 타입 범위를 넘을 경우에는 오버플로우가 발생해 예상치 못한 값이 될 수 있다.
예시)
int intNum = 32767+1;
short shortNum = (short) intNum;
System.out.println(shortNum); // -32768
여기서부터 살짝 TMI
위에서 왜 -32768이 출력되는지를 알기 위해 Java에서 메모리에 데이터가 어떻게 저장되는지를 보자.
메모리가 Data에 적재되는 방식에는 Big Endian과 Little Endian 방식이 있다.
사람과 동일하게 앞에서부터 순차적으로 데이터를 저장한다.
ex) 12345678
주소 | 0x0001 | 0x0002 | 0x0003 | 0x0004 |
---|---|---|---|---|
Data | 0x12 | 0x34 | 0x56 | 0x78 |
Big Endian과 반대로 역순으로 데이터를 저장한다.
ex) 12345678
주소 | 0x0001 | 0x0002 | 0x0003 | 0x0004 |
---|---|---|---|---|
Data | 0x78 | 0x56 | 0x34 | 0x12 |
Java는 이 중 Big Endian 방식으로 메모리를 적재한다.
그리고 컴퓨터는 음수를 어떻게 저장할까?
음수를 표현하는 방식에는 크게 세가지가 있다.
맨 앞 비트를 부호 비트로 사용하는 방법이다. 부호 비트가 0이면 양수, 1이면 음수이다.
+3 = 0000 00112
-3 = 1000 00112
이 경우 둘을 더했을 때 0이 되지 않아 이진수 계산이 불가능하다.
양수 값의 비트를 반전시켜 음수를 표현하는 방법이다.
+3 = 0000 00112
-3 = 1111 11002
이 경우 0000 00002과 1111 11112 둘다 0이 되어 0이 두개가 되는 문제가 있다.
1의 보수 방법에 1을 더하는 방법이다.
+3 = 0000 00112
-3 = 1111 11012
이 경우 1111 11112이 -1이 되어 0과 구별이 가능하다.
또한, 두 값을 더했을 때 0000 0000이 되어 0이 되게 된다.
(원래는 0001 0000 0000이 되어야 하지만 범위를 넘는 비트는 표현되지 않아 0이 된다.)
이제 int 타입으로 32768을 표현해보자.
0000 0000 0000 00000 1000 0000 0000 0000
이 값을 short 타입으로 변환시키면 앞의 16 bit가 범위에 포함되지 않아 아래와 같은 비트가 남는다.
1000 0000 0000 0000
해당 값은 short로 -32768이 된다.
2진수 | 부호있는 10진수 |
---|---|
0000 0000 0000 0000 | 0 |
0000 0000 0000 0001 | 1 |
... | ... |
0111 1111 1111 1111 | 32767 |
1000 0000 0000 0000 | -32768 |
1000 0000 0000 0001 | -32767 |
... | ... |
1111 1111 1111 1110 | -2 |
1111 1111 1111 1111 | -1 |