티스토리 뷰
주의 사항!
- 이 글은 제가 직접 공부하는 중에 작성되고 있습니다.
- 따라서 제가 이해하는 그대로의 내용이 포함됩니다.
- 따라서 이 글은 사실과는 다른 내용이 포함될 수 있습니다.
타입 변환이란 데이터 타입을 다른 데이터 타입으로 변환하는 것을 말합니다. 예를 들어 byte타입을 int 타입으로 변환하거나 반대로 int 타입을 byte타입으로 변환하는 행위를 말합니다.
타입 변환에는 두 가지 종류가 있습니다. 하나는 '자동(묵시적) 타입 변환'이고, 다른 하나는 '강제(명시적) 타입 변환'입니다.
자동 타입 변환
자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말합니다. 자동 타입 변환은 작은 크기를 가지는 타입이 큰 크기를 가지는 타입에 저장될 때 발생합니다.
작은 타입과 큰 타입을 구분하는 기준은 각 데이터 타입의 메모리 크기입니다. 예를 들어 int타입은 메모리 크기가 4바이트고, short 타입은 2바이트이므로 int가 short보다 큰 타입이 됩니다. 반면 long은 8바이트이므로 int가 double보다는 작은 타입이 됩니다.
대부분의 경우에서 데이터 타입의 크기만으로 크기 비교를 하지만, 어떤 경우에 한해서는 데이터 타입의 크기만으로 크기 비교를 할 수는 없습니다. 예를 들어 long 타입과 float 타입을 비교해 보겠습니다. long타입은 8바이트고, float타입은 4바이트입니다. 따라서 float가 long 보다는 작은 타입이 되어야 하지만, float이 long보다 더 큰 타입으로 봅니다. 왜냐하면 float은 실수형 데이터 타입이고, long보다 더 큰 데이터를 표현할 수 있기 때문입니다.
사실 바이트 수가 많을수록 표현할 수 있는 데이터의 크기가 더 커지기 때문에 따지고 보면 표현할 수 있는 데이터의 크기를 가지고 큰 타입인지 작은 타입인지를 비교한다고 볼 수 있겠습니다.
그래서 일반적으로 정수 타입보다는 실수 타입이 더 크고, 정수 타입이나 실수 타입 내에서는 바이트 수가 클수록 큰 타입으로 볼 수 있습니다. 물론 예외는 있습니다. char타입과 byte타입은 둘 다 정수형 타입이고, char타입은 2바이트의 크기, byte타입은 1바이트의 크기를 가집니다. 그런데 byte 타입을 자동 타입 변환하여 char타입에 저장할 수는 없습니다. 이유는 char타입은 음수를 표현할 수 없기 때문입니다. char타입은 유니코드를 표현할 목적을 가지고 있기 때문에 음수는 필요가 없어서 음수를 표현할 조합까지 양수를 더 많이 조합하는 것에 사용합니다. 그런데 byte는 비록 표현할 수 있는 데이터 크기는 작아도 음수를 표현할 수 있기 때문에 음수를 표현할 수 없는 char에는 저장할 수 없습니다.
강제 타입 변환
큰 타입은 작은 타입으로 자동 타입 변환을 할 수 없습니다. 예를 들어 4바이트의 int타입을 1바이트의 byte타입으로 변환할 수 없습니다. 이런 타입 변환이 일어나면 데이터의 손실이 발생할 수 있습니다. int타입은 60,000을 표현할 수 있습니다. 하지만 byte타입은 이 숫자를 표현할 수 없습니다. 따라서 int타입 60,000을 byte타입으로 변환하면 60,000이라는 데이터는 소실될 것입니다.
하지만 데이터 손실의 문제만 피할 수 있다면 타입 변환을 해도 괜찮을 것 같습니다. 예를 들어 int타입에 저장된 데이터가 10이라면, 이는 byte타입으로도 표현할 수 있습니다. 따라서 int타입의 10을 byte 타입으로 변환해도 데이터 손실이 발생하지 않습니다.
int num = 60000;
byte value = (byte)num; //데이터 손실 발생
int num = 10;
byte value = (byte)num; //데이터 손실 발생하지 않음
강제 타입 변환을 할 때는 위의 예처럼 변수명 앞에 변환하고자 하는 데이터 타입을 소괄호로 묶어서 명시해줍니다. 위 예에서는 num를 byte타입으로 변환하기 위해 byte를 소괄호로 묶어 명시했습니다.
실수 타입을 정수 타입으로 강제 타입 변환하면 소수점 이하의 데이터들은 버려집니다.
double dbNum = 12.3456;
int num = (int)dbNum; //12
정수 타입을 실수 타입으로 강제 타입 변환할 때는 정밀도의 손실을 생각해야 합니다.
float과 double과 같은 실수 타입은 숫자를 부동소수점으로 표현합니다. 부동소수점이 무엇인지는 검색해보면 알 수 있을 것입니다. 부동소수점은 숫자를 표현하는 하나의 방법입니다. 일반적으로 123456으로 표현할 수 있는 숫자를 1.23456 * 10^2으로 표현하는 것과 같습니다. 이때 1.23456을 가수라고 하고, 10의 지수인 2를 지수라고 합니다.
float은 비트 수가 총 32개인데 그중 가장 앞의 하나는 부호를 나타내는 데 사용하며, 지수를 표현하는 데에 8비트, 그리고 가수를 표현하기 위해 나머지 23비트를 사용합니다. 정수 타입을 실수 타입으로 강제 변환할 때, 정수 타입의 데이터를 손실 없이 변환하려면 가수만으로 해당 데이터를 표현할 수 있어야 합니다.
그런데 예를 들어 int타입은 31비트로 데이터를 표현하고(부호 비트 제외), float타입의 가수는 23비트에 불과하므로 float타입의 가수만으로는 표현할 수 없는 int타입 데이터가 존재할 수 있습니다. 예를 들면 10,000,000과 같은 데이터입니다. 이런 데이터를 float타입으로 변환할 때는 온전한 10,000,000이 아닌 9,999,999.9999875와 같은 데이터로 변환될 수 있습니다.
double타입은 가수를 표현하기 위해 52비트를 사용하기 때문에 int타입의 데이터는 충분히 수용할 수 있지만, long타입을 변환하여 수용할 때는 역시 정밀도의 손실을 생각해야 합니다.
연산식에서의 자동 타입 변환
연산은 기본적으로 같은 타입의 피연산자 간에만 수행되기 때문에 서로 다른 타입의 피연산자가 있을 경우 두 피연산자 중 크기가 큰 타입으로 자동 변환된 후 연산을 수행합니다. 예를 들어 int타입 피연산자와 double 타입 피연산자를 덧셈 연산하면 int타입이 먼저 double 타입으로 변환되고 연산이 수행됩니다. 결과는 double타입이 됩니다.
int num1 = 10;
double num2 = 11.52;
double result = num1 + num2; //21.52
만약 위 연산을 int타입으로 하고 싶다면 double을 강제로 int타입으로 변환 후 연산을 수행하면 됩니다
int num1 = 10;
double num2 = 11.52;
int result = num1 + (int)num2; //21
자바는 정수 연산일 경우 int 타입을 기본으로 합니다. 왜냐하면 피연산자를 4바이트 단위로 저장하기 때문입니다. 따라서 int 타입보다 작은 정수형 타입은 int 타입으로 자동 변환된 후 연산되며, 연산 결과 역시 int 타입이 됩니다.
char ch1 = 'A';
char ch2 = 'B';
int result1 = ch1 + ch2; //'A'의 유니코드 값과 'B'의 유니코드 값을 더한 값 저장
char result2 = ch1 + ch2; //에러 발생
이런 특징 때문에 똑같은 char 타입끼리의 연산에서도 이들은 int 타입으로 변환되어 연산되며, 연산 결과 역시 int 타입이 되기 때문에 int타입 변수에 이를 저장할 수 있습니다.
그런데 다음과 같은 경우에는 다릅니다.
char ch1 = 'A' + 'B'; //65 + 66
char ch2 = 'A' + 1; //65 + 1 = 66 = 'B'
이렇게 피연산자가 리터럴만으로 구성되어 있으면 굳이 int 타입으로 변환하여 연산하지는 않습니다.
'공부 일지 > JAVA 공부 일지' 카테고리의 다른 글
자바, 열거 타입 (0) | 2021.04.05 |
---|---|
자바, 향상된 for문 (0) | 2021.04.05 |
자바, 데이터 타입 (0) | 2021.04.05 |
자바, 리터럴 (0) | 2021.04.05 |
자바, 변숫값 저장 (0) | 2021.04.05 |