💁 형변환(Casting)이란,
자동 혹은 강제적으로 데이터의 타입을 변경하는 것
📌 Ref.
* 형변환이 필요한 이유 ?
자바에서 연산은 피연산자들이 모두 같은 타입인 경우 실행할 수 있음
즉, 같은 데이터 타입끼리만 연산을 수행할 수 있음
📍 자동 형변환이 되는 경우
1) 작은 자료형에서 큰 자료형으로 공간을 옮길 때
2) 정수는 실수와 연산될 때 실수로 형변환
3) 문자형은 int형으로 형변환
4) 논리형은 형변환 규칙에서 제외
작은 자료형에서 큰 자료형으로 공간만 옮기는 경우 데이터 손실이 발생하지 않기 때문에 컴파일러가 자동으로 처리
byte bnum = 1;
short snum = bnum;
int inum = snum;
long lnum = inum;
>>> 점점 더 큰 자료형으로 데이터를 옮겨도 문제 없이 자동 형변환 처리
int num1 = 10;
long num2 = 20;
//int result1 = num1 + num2;
>>> 자동으로 큰 자료형인 long으로 변경 후 계산하기 때문에 int에 담을 수 없음
long result1 = num1 + num2;
>>> int -> long 변환을 자동 수행 후 연산함
📌 Ref.
* 연산 시, 자동으로 큰 쪽 자료형에 맞춰서 계산
float fnum = 4.0f;
double dnum = fnum;
//float result2 = fnum + dnum;
>>> 이미 값은 double 형태기 때문에 float에 담을 수 없음
double result2 = fnum + dnum;
정수를 실수로 변경할 때 소수점 자리수가 없어도 실수 형태로 표현이 가능함
이 때, 데이터 손실이 없기 때문에 자동 형변환이 가능함
정수는 실제 값을 저장하는 매커니즘을 가진 것과 달리 실수는 지수부와 가수부를 따로 나눠서 작성하기 때문에 바이트의 크기보다 훨씬 더 많은 값을 표현할 수 있음
📌 Ref.
* 특히 long(8byte) -> float(4byte), long은 float보다 크지만 실수가 표현할 수 있는 범위가
굉장히 넓기 때문에 자동 형변환
* but float -> long은 안됨 (강제 형변환 필요)
long eight = 8;
float four = eight;
float result3 = eight + four;
System.out.println("result3 : " + result3);
>>> 따라서, 실수와 정수의 연산은 실수로 연산 결과가 반환
📌 Ref.
* long(정수) + float(실수) = 실수
char(2byte)는 short(2byte)와 크기가 같지만 표현할 수 있는 범위가 달라서 int, long 등으로 자동 형변환은 되지만 short만은 안됨
char ch1 = 'a';
int charNumber = ch1;
System.out.println("charNumber : " + charNumber);
>>> char가 가지는 범위 안의 정수는 char형 변수에 기록 가능
char ch2 = 65;
>>> 'a'유니코드 = 65
System.out.println("ch2 : " + ch2);
📌 Ref.
* char의 범위인 0 ~ 65,535 까지만 가능
어느 자료형이든 boolean을 형변환해서 담을 수 없음
boolean isTrue = true;
//byte b = isTrue;
📍 강제 형변환이 되는 경우
1) 큰 자료형에서 작은 자료형으로 공간을 옮길 때
2) 실수를 정수로 연산하고자 할 때 형변환
3) 문자형을 int형미만 크기의 변수에 저장하고자 할 때 형변환
4) 논리형은 강제 형변환 규칙에서도 제외
long lnum = 8L;
//int inum = lnum;
>>> 데이터 손실 가능성을 컴파일러가 알려줌 (에러 발생)
int inum = (int)lnum;
short snum = (short)inum;
byte bnum = (byte)snum;
>>> 변경하려는 자료형을 명시하여 강제 형변환 해야함
double dnum = 8.0;
float fnum = (float)dnum;
float fnum2 = 4.0f;
long lnum2 = (long)fnum2;
>>> float는 4byte, long은 8byte임에도 자동 형변환 불가능
>>> (실수 -> 정수 X : 소수점 자리 이하 데이터 손실 가능성)
char ch = 'a';
byte bnum2 = (byte)ch;
short snum2 = (short)ch;
📌 Ref.
* char와 short는 둘 다 2byte로 같은 크기인데 강제 형변환 해야하는 이유는?
부호 비트로 인한 값의 범위가 다르기 때문 (맨 아래 '변수 저장 가능 범위표' 참조)
boolean isTrue = true;
//byte b = (byte) isTrue;
>>> 강제 형변환을 해도 전부 에러
다른 자료형끼리의 연산은 큰 자료형으로 자동 형변환 후 연산 처리됨
int inum = 100;
long lnum = 100L;
// way 1. 두 수의 연산 결과를 int형으로 변환 후 int 자료형 변수에 리턴 받음
int isum = (int) (inum + lnum);
// way 2. long형 값을 int로 강제 형변환
int isum2 = inum + (int) lnum;
// way 3. 결과 값을 long형 자료형으로 받음
long lsum = inum + lnum;
>>> 자동 형변환 (가장 자연스러운 방법)
int 미만의 자료형의 연산 처리 결과는 항상 int형
byte byteNum1 = 1;
byte byteNum2 = 2;
short shortNum1 = 3;
short shortNum2 = 4;
// byte result1 = byteNum1 + byteNum2;
>>> byte를 int로 설정해줘야함
int result1 = byteNum1 + byteNum2;
// short result2 = shortNum1 + shortNum2;
>>> short를 int로 설정해줘야함
int result2 = shortNum1 + shortNum2;
int inum = 234;
byte bnum = (byte) inum;
>>> byte 값의 범위는 -128 ~ 127이기 때문에 출력했을 때, 데이터 손실로 인해 생뚱맞은 값 출력
System.out.println("inum : " + inum);
System.out.println("bnum : " + bnum);
>>> 비트 앞부분 손실로 값을 예측하기 어려움
double height = 173.5;
int floorHeight = (int) height;
System.out.println("height : " + height);
System.out.println("floorheight : " + floorHeight);
>>> 의도적으로 실수의 소수점 부분을 절삭에 이용할 수 있음
📌 Ref.
🔑 Used Keywords
형변환
변수 저장 가능 범위