이번 포스팅에서는 자바(Java)의 형 변환(type conversion)에 대하여 공부를 해보고자 한다.
형 변환이란
하나의 타입을 다른 타입으로 바꾸는 것을 형 변환(type conversion)이라고 한다
자바에서는 boolean형을 제외한 나머지 기본 타입 간의 타입 변환을 자유롭게 수행할 수 있다.
자바에서 다른 타입끼리의 연산은 우선 피연산자들을 모두 같은 타입으로 만든 후에 수행된다.
int n = 10; //int형 변수 n에 정수 값 10을 대입
double dnum = n; //int형 변수 n의 값을 double형 변수 dnum에 대입
위 코드에서 변수 n은 int형이고 변수 dnum은 double형이다.
형 변환이란 이렇게 각 변수의 자료형이 다를 때 자료형을 같게 바꾸는 것을 말한다.
형 변환의 종류
자바에서 형 변환은 크게 다음과 같이 두 가지 방식으로 나뉜다.
- 묵시적 타입 변환(자동 타입 변환)
- 명시적 타입 변환(강제 타입 변환)
형 변환의 기본 원칙
- 바이트 크기가 작은 자료형에서 큰 자료형으로 형 변환은 자동으로 이루어진다.
- 덜 정밀한 자료형에서 더 정밀한 자료형으로 형 변환은 자동으로 이루어진다.
위 두 가지 원칙에 기반하여 묵시적 형 변환이 이루어지는 관계를 살펴보면 다음과 같다.
- 위 그림에서 화살표 방향과 반대로 형 변환을 하려면 강제로 변환해야 한다.
- 화살표 방향으로 형 변환이 이루어질 때는 자료 손실이 없지만, 그 반대인 경우에는 자료 손실이 발생할 수 있다.
묵시적 형 변환
묵시적 형 변환(자동 형 변환, implicit conversion)이란 대입 연산이나 산술 연산에서 컴파일러가 자동으로 수행해 주는 형 변환을 말한다.
자바에서는 데이터의 손실이 발생하지 않거나, 데이터의 손실이 최소화되는 방향으로 묵시적 타입 변환을 진행한다.
또한, 자바에서는 데이터의 손실이 발생하는 대입 연산은 허용하지 않는다.
바이트 크기가 작은 자료형에서 큰 자료형으로 대입하는 경우
byte = bNum = 10;
int iNum = bNum; //byte형 변수 bNum 값을 int형 변수 iNum에 대입함
이 경우에 bNum의 크기는 1바이트이고 iNum의 크기는 4바이트이므로 자료 손실 없이 bNum에 들어 있는 값이 모두 iNum에 저장된다.
남은 3바이트에는 0으로 채워진다.
덜 정밀한 자료형에서 더 정밀한 자료형으로 대입하는 경우
int iNum2 = 20;
float fNum = iNum2;
이 경우에는 두 변수의 크기가 같은 4바이트라도 float형인 fNum이 더 정밀하게 데이터를 표현할 수 있으므로 실수형인 float형으로 변환된다.
연산 중에 자동 변환되는 경우
int iNum = 20;
float fNum = iNum;
double dNum;
dNum = fNum + iNum;
이 경우에는 dNum = fNum + iNum에서 두 번의 형 변환이 일어난다.
먼저 fNum + iNum 연산에서 int형이 float형으로 변환되고, 두 변수를 더한 결과 값이 dNum에 대입되면서 double형으로 변환된다.
바이트 크기가 작은 수에서 큰 수로, 덜 정밀한 수에서 더 정밀한 수로 자료형이 변환되는 경우 자동 형 변환이 일어난다.
명시적 형 변환
명시적 형 변환(강제 형 변환, explicit conversion)이란 사용자가 타입 캐스트 연산자(())를 사용하여 강제적으로 수행하는 타입 변환을 말한다.
묵시적 형 변환과 반대의 경우로 생각할 수 있다.
자바에서는 다음과 같이 명시적 타입 변환을 수행할 수 있다.
(변환할 타입) 변환할 데이터
변환시키고자 하는 데이터의 앞에 괄호(())를 넣고, 그 괄호 안에 변환할 타입을 적으면 된다.
자바에서는 이 괄호를 타입 캐스트(type cast) 연산자라고 합니다.
바이트 크기가 작은 자료형에서 큰 자료형으로 대입하는 경우
int iNum = 10;
byte bNum = (byte)iNum; //강제로 형을 바꾸려면 바꿀 형을 괄호를 써서 명시해야 함
byte형은 1바이트로 int형보다 크기가 작기 때문에 자료 손실이 발생할 수 있다.
변환할 자료형을 명시적으로 써 주어야 하며 이를 강제 형 변환이라고 한다.
이 경우에는 대입된 값 10을 1바이트 안에 표현할 수 있으므로 자료 손실이 없다.
그러나 다음처럼 byte형이 표현할 수 있는 범위를 넘는 경우에는 자료 손실이 발생할 수 있다.
int iNum = 1000;
byte bNum = (byte)iNum;
값 1000이 byte형 범위(-128~127)를 넘기 때문에 자료 손실이 발생해 대입된 값이 -24로 출력된다.
더 정밀한 자료형에서 덜 정밀한 자료형으로 대입하는 경우
실수 자료형에서 정수 자료형으로 값이 대입되는 경우에도 역시 형 변환을 명시적으로 해주어야 한다.
double dNum = 3.14;
int iNum2 = (int)dNum; //실수 자료형 double을 정수 자료형 int로 형 변환
실수의 소수점 이하 부분이 생략되고 정수 부분만 대입된다.
연산 중 형 변환
연산 중에 명시적으로 형 변환을 하는 예제
public class ExplicitConversion {
public static void main(String[] args) {
double dNum1 = 1.2;
float fNum2 = 0.9F;
int iNum3 = (int)dNum1 + (int)fNum2; //두 실수가 각각 형 변환되어 더해짐
int iNum4 = (int)(dNum1 + fNum2); // 두 실수의 합이 먼저 계산되고 형 변환됨
System.out.println(iNum3);
System.out.println(iNum4);
}
}
- 8행과 9행의 연산 결과가 다르다.
- 8행에서는 두 실수가 각각 명시적으로 형 변환이 일어나기 때문에 1과 0으로 변환된 두 값을 합하여 결과값이 1이 된다.
- 9행에서는 두 dNum1과 fNum2의 합을 먼저 계산한다.
- 이때 두 실수의 자료형이 다르지만 float형이 double형으로 변환되는 묵시적 형 변환이 일어나면서 두 수가 더해져 결과값이 2.1이 되고, 이후에 int형으로 명시적 형 변환이 되어 결과 값이 2가 된다.
같은 연산이라도 형 변환이 언제 이루어졌는지에 따라 그 결과 값이 다르게 나타날 수 있다.
'Back-End > Java' 카테고리의 다른 글
[Java] 비트 연산자 (2) | 2023.01.28 |
---|---|
[Java] 기본 연산자 (0) | 2023.01.28 |
[Java] 상수와 리터럴 (2) | 2023.01.27 |
[Java] 논리 자료형 (0) | 2023.01.26 |
[Java] 실수 자료형 (0) | 2023.01.26 |