타입을 다른 타입으로 바꾸는 것. 바이트 크기가 작은 자료형에서 큰 자료형으로, 덜 정밀한 자료형에서 더 정밀한 자료형으로 가는 방향은 자동으로 이뤄진다. 값이 손실되지 않기 때문이다.
묵시적 형 변환
작은 쪽에서 큰 쪽으로 대입하면 컴파일러가 알아서 바꿔준다. 묵시적 형 변환이라고 부른다.
byte bNum = 10;
int iNum = bNum; // 10
byte neg = -1;
int iNeg = neg; // -1
int iNum2 = 20;
float fNum = iNum2; // 4바이트끼리지만 float가 더 정밀하다1바이트가 4바이트로 늘어날 때 남는 앞자리는 부호 비트 값으로 채워진다. 양수 10은 00001010이라 앞이 0으로 채워져 그대로 10이지만, -1은 11111111이라 앞 3바이트까지 1로 채워져 4바이트 전체가 11111111 11111111 11111111 11111111, 다시 -1이 된다. 어느 쪽이든 값은 그대로 남아 자료 손실이 없다.
명시적 형 변환
반대 방향은 값이 잘릴 수 있어서 개발자가 직접 책임을 진다. (타입)을 앞에 붙여 알고 있으니 그대로 하라고 표시하는 것이 명시적 형 변환이다.
int iNum = 10;
byte bNum = (byte) iNum; // 10, 1바이트에 들어가니 손실 없음
int iNum2 = 1000;
byte bNum2 = (byte) iNum2; // -24, byte 범위(-128~127)를 벗어나 잘림
double dNum = 3.14;
int iNum3 = (int) dNum; // 3, 소수점이 버려진다변환 시점이 가르는 결과
형 변환이 언제 일어나는지도 결과를 가른다.
double dNum1 = 1.2;
float fNum2 = 0.9F;
int iNum3 = (int) dNum1 + (int) fNum2; // 1 + 0 = 1
int iNum4 = (int) (dNum1 + fNum2); // 2.1 을 잘라 2정수 타입으로서의 char
char는 형 변환을 이해하기에 좋은 예다. 작은따옴표로 묶인 문자 하나를 담고, 2바이트 크기에 유니코드 값을 갖는다. 유니코드표에서 A는 0041, a는 0061이고 10진수로 바꾸면 각각 65와 97이다.
문자를 담는다고 하지만 실제로 저장되는 것은 그 문자에 해당하는 정수 값이다. char가 정수 타입인 셈이라 이런 계산이 성립한다.
char c = 'A';
int i = c; // 65, 자동 형 변환
char next = (char)(c + 1); // 'B'같은 2바이트인 short와는 표현 범위가 다르다. short는 -32,768부터 32,767까지 음수를 포함하고, char는 0부터 65,535까지 0과 양수만 담는다. 부호 비트를 쓰지 않는 만큼 양의 방향으로 두 배 넓다. 그래서 char를 int로 늘릴 때만은 앞자리가 0으로 채워진다.
'A'가 65라는 것을 알아두면 문자열 문제가 쉬워진다.
c - 'A' // 알파벳 순서 (0부터)
c - 'a' // 소문자 순서
c - '0' // 문자 숫자를 정수로참고
원본은 byte를 int로 넓힐 때 “남은 3바이트는 0으로 채워짐”이라고 적었다. byte는 부호 있는 타입이라 부호 확장이 일어난다. 자바 언어 명세는 부호 있는 정수 타입을 넓힐 때 부호 비트를 확장하고, char처럼 부호 없는 타입일 때만 0으로 확장한다고 정한다. byte b = -1; int i = b;의 결과가 0이 아니라 -1인 이유다. JLS 5.1.2