자료형을 다른 자료형으로 변환하는 것을 말하며, 자동(묵시적)형변환과 강제(명시적)형변환으로 구분
예를 들어 byte 타입의 자료형을 int 타입으로 변환하거나 그 반대로 변환하는 행위를 이야기한다.
자동형변환은 작은 데이터 사이즈를 가지는 타입이 더 큰 데이터 사이즈를 가지는 타입에 저장될 때 자동으로 변환이 일어난다. 아래 정수형 변수의 데이터 사이즈를 참고하면서 알아가보자.
형의 이름 | 읽는 법 | 들어가는 값의 범위 | 사이즈(비트 수) |
---|---|---|---|
byte | 바이트 | -128 ~ 127 | 8 |
short | 쇼트 | -32768 ~ 32767 | 16 |
int | 인트 | -2147483648 ~ 214783647 | 32 |
long | 롱 | -9223372036854775808 ~ 9223372036854775807 | 64 |
데이터의 크기를 비교할 때에는 사이즈(비트 수)를 참고하면된다. 참고로 long형은 8byte의 데이터 사이즈를 가지고, float형은 4byte의 사이즈를 가진다. 둘중 누가 더 큰 타입이라고 할 수 있을까? 당연히 8byte가 크다고 생각할 수 있지만 아쉽게도 float이 더 크다. 이유는 float형이 표현할 수 있는 값의 범위가 더 크기 때문이다. 이 부분만 유의하면 데이터 타입 크기를 비교하는 것은 어렵지 않다. 그럼 아래 예시를 보자.
//정수 자료형의 자동형변환
//1
byte b = 10; //1byte 크기의 자료형
//2
int i = b; //4byte 크기의 자료형
위 코드에서 1번에서는 변수를 선언과 동시에 초기화하고, 2번에서 byte형 변수를 int형 변수에 대입해주었다. 이 부분에서 자동형변환이 일어난다. 자동형변환은 데이터 사이즈가 작은 타입이 큰 타입으로 변환되는 것이기 때문에 변환 이전과 이후의 값은 동일하다. 즉 데이터의 손실이 발생하지 않는다.
//1
int i = 10; //정수형 변수선언 및 초기화
//2
double d = i; //실수형 변수에 정수형 변수 대입
위 코드는 정수 자료형을 실수 자료형으로 형변환을 하는 것이다. 여기서 int형 데이터 사이즈는 4byte, double형 데이터 사이즈는 8byte이다. 데이터 사이즈에 대해서는 위에서와 동일하게 작용하며, 여기서 중요한 것은 정수 타입이 실수 타입으로 형변환 할 경우에도 무조건 자동형변환이 일어난다. 즉, 아래와 같이 변환이 된다.
int i = 100;
double d = i;
//현재 d의 값 = 100.0
그렇다면 문자형과 수치형의 자동형변환에 대해서 알아보자. 앞선 게시글에서 설명한 것처럼 문자 자료형인 char형은 unsigned로 음수값을 가지지 않고 0부터 시작하는 양수값만 가지는 자료형이다. 이 점에 유의하여 알아보자.
//1
char c = '가'; //문자형 변수 선언 및 초기화
//2
int i = c; //정수형 변수 선언 및 문자형 대입
//3
//현재 i의 값은 = 65
문자형은 유니코드를 기반으로 한다. 이는 문자를 그대로 컴퓨터가 인식하는 것이 아닌 숫자로 번역하여 읽는다고 생각하면 된다. 즉, 문자를 숫자로 바꾸는 유니코드 값이 정수형 타입에 저장이 되는 것이다. 또한, 위에 설명한대로 음수값을 가지지 않기 때문에 음수가 저장될 수 있는 byte형을 char형으로 자동형변환 할 수 없다.(강제형변환을 통해서는 가능하니 잠시후에 알아보도록하자)
자동형변환은 정원이 정해진 텅빈 엘리베이터에 정원에 맞는 사람들이 정원초과없이 들어갈 수 있는 것과 비슷한 개념이다.
즉, 엘리베이터에 못타는 사람이 없는 것처럼 큰 크기의 데이터로 형변환이 되는 것이기 때문에 데이터의 손실이 없다는 것이다.
강제형변환은 큰 데이터 사이즈의 자료형이 작은 데이터 사이즈의 자료형으로 변환되는 것을 말한다. 자동형변환과의 차이점은 크게 두 가지이다.
먼저, 데이터가 큰 자료형을 작은 자료형으로 넣기 위해서는 말 그대로 강제로 넣어줘야한다. 변수 관계에서 강제로 형변환을 하기 위해서는 () 캐스팅 연산자를 사용하여 변환하고자하는 자료형을 명시해준다. 아래 예시를 보자.
int i = 100; //4byte 크기의 자료형
byte b = (byte)i; //1byte 크기의 자료형으로 변환(명시)
여기서 int형 변수 i는 byte형 변수 b로 변환이 실행되어진다. 이때, i의 값이 100이고, 100은 b의 데이터 범위 내에 포함되므로 데이터의 손실이 발생하지 않는다. 이 말은 데이터 범위가 초과되면 초과된 만큼의 데이터 손실이 발생한다는 것이다. 다른 예시도 둘러보자.
int i = 'A'; //int형 변수 선언과 유니코드 내 양수를 가지는 데이터를 대입
char c = (char)i; //i가 가지고 있는 유니코드 값을 char형에 대입
int형은 char형으로 자동 형변환이 불가능하다. 이것은 int는 음수의 값도 포함할 수 있기 때문에 명시적으로 형변환을 해주어야한다.(앞서 설명한 byte도 동일) 이 말은 유니코드 범위(0~65535)내에 값을 int형이 가지고 있다면 정상적으로 강제형변환이 가능하다는 것이다. 다음은 실수와 정수의 관계 간의 강제형변환을 알아보자.
double b = 3.14; //8byte 크기의 변수 선언 및 초기화
int i = (int)b; //4byte 크기의 변수에 대입
//현재 i의 값 = 3;
위 코드를 보면 실수형은 정수형으로 자동형변환이 불가능하다. 이는 데이터의 표현범위와 데이터 사이즈와 연관이 있다. 실수형을 정수형을 형변환 시 반드시 소수점 이하 부분은 버려지고, 정수 부분만 저장이 되기에 데이터의 손실은 불가피하다. b의 값인 3.14를 i에 대입하면 .14는 사라지고 3만 i의 데이터로 저장된다. 실제 코드를 작성하다보면 의도적으로 사용하는 경우들도 있지만 이 점에 유의하여 사용하기 바란다.
강제형변환은 마치 정원이 거의 다찬 엘리베이터에 탑승하려다가 엘리베이터를 타지 못하는 사람들이 발생하는 것과 비슷한 개념이다.
즉, 온전히 가져가야할 데이터의 손실이 발생할 수 있다는 것이다. 사용자가 어떠한 데이터를 입력하였는데, 그 데이터가 코드에 의해 강제형변환이 이루어져 데이터의 손실이 발생한다면 금전적인 피해로 다가갈 수도 있기 때문에 데이터 손실의 여부를 세밀하게 고려해야한다.
이번 게시글에서는 기본자료형의 형변환에 대하여 간단하게 알아보았다. 실제로 코드를 작성하다보면 형변환을 해야하는 경우들이 많이 발생한다. 의도치 않게 데이터의 손실이 발생하는 경우도 생기고, 미처 신경쓰지 못한 부분에서 컴파일 에러가 발생하는 경우들도 다반사다. 이러한 것을 아예 제거하기는 힘들겠지만 최소화하기 위해서는 형변환의 개념에 대해서 이해하고, 사용하기 전에 한번 더 생각을 해보고 사용을 해야한다는 점을 인식하기를 바란다.