11
25

pixabay 저작권 무료 이미지 by thehalaldesign

 

형 변환(Casting / Type Conversion)

형 변환은 어느 한 변수에 담았던 값을 다른 변수 타입에 담는 것이다.

[1주차] 1. 기본 자료형과 변수 - 기본편을 이미 보았다면 이렇게 생각해보자.

 

파티 가방으로 쓰는 엘리자베스장바구니로 쓰는 마봉팔이 있다. 원래라면 엘리자베스에 파티 물품을 넣고, 장바구니에 마트 물품을 담을 것이다.

 

하지만 당신이 파티 가방에 마트 물품을 넣고 싶다면 어떨까? 프로그래밍에서는 그러한 행위가 불가능한 것일까?

 

한 마디로 답하겠다. 가능하다.

 

우리는 일전 포스트에서 기본 자료형의 종류를 알아보았다. 그 중 boolean을 제외한 7개의 기본형은 서로 형변환이 가능하다.

 

다른 말로 말하자면 우리가 옛날에 공병 팔아 엿 바꿔 먹었듯이, 이 7개의 기본 자료형들은 서로 변수를 바꿔먹는 형 변환을 해도 상관 없다는 것이다.

 

형 변환의 종류에는 자동(묵시적) 형 변환과 강제(명시적) 형 변환이 있는데, 이 두 가지를 알아보도록 하자.

 

 

 

자동-묵시적 형 변환(Automatic-Implicit Type Conversion)

자동 형 변환. 이름부터가 그 성질을 대변하고 있지 않은가? 우리가 뭘 난리치고 지지고 볶든 그냥 자동으로 형이 변환된다는 거다.

 

 

기본 자료형 중 정수형에는 byte, short, int, long이 있고 실수형에는 float와 double이 있다고 말했었다. 각기 다른 범위도 간단히 소개를 했었는데, 이 범위가 형 변환이 자동일지 강제일지를 정하는 열쇠가 된다.

 

정수형은 long, int, short, byte순으로 크며, 실수형은 double, float 순으로 크다.

 

좁히는(자동) 형 변환과 늘리는(강제) 형 변환

java T point website

 

위의 이미지는 그 범위를 나타내고 있다. 소수점을 포함할 수 없는 정수형은 소수점도 포함할 수 있는 실수형보다 크다고 보기 때문에 double가 float가 가장 큰 범위로서 자리잡고 있다. 단, float는 long보다 4바이트 적은 범위의 숫자를 나타낼 수 있다는 것에 유의해야 한다.

 

 

byte -> short -> char -> int -> long -> float -> double

 

byte b = 17;
int i = b;

System.out.println(i);			// 결과 = 17

 

위의 예제는 byte형인 b를 int형인 i에 담은 것이다.

 

위와 같이 작은 숫자를 더 큰 숫자 안에 담는 것에는 문제가 없다. 소주잔에 들어있는 소주를 맥주잔에 넣으려고 하면 어떨까? 문제가 생기나?

 

전혀 생기지 않는다. 당신은 맛있는 소맥을 말아먹을 수 있을 것이다.

 

작은 잔에 담겨있던 내용물을 큰 잔에 옮긴다 한들 그 어떠한 불편도, 에러도 따르지 않는다.

 

이렇게 작은 범위(byte)로 선언되었던 변수(b)를 더 큰 범위(int)의 변수(i)에 담으려 할 때는, 자동적으로 형 변환 (byte -> int)이 되어 문제 없이 형 변환을 할 수 있게 된다.

 

이를 자동 형 변환 또는 묵시적 형 변환이라 한다.

 

 

 

강제-명시적 형 변환(Manual-Explicit Type Conversion)

위에서 자동 형 변환에 대한 설명을 들었을 때, 당신은 궁금해 했을 것이다.

 

그렇다면 더 큰 범위로 선언된 변수를 작은 범위로 선언된 변수 안에 담고 싶다면 어떻게 해야할까?

 

 

그러한 경우에는 강제 형 변환(명시적 형 변환)을 적용해야 한다.

 

double -> float -> long -> int -> char -> short -> byte

 

int i = 17;
byte b = (byte)i;

System.out.println(b);			// 결과 = 17

 

위의 예제는 int형인 i를 byte형인 b에 담은 것이다. 아까와 변수의 순서만 바꾸었다.

 

위와 같이 큰 범위(int)로 선언되었던 변수(i)를 더 작은 범위(byte)의 변수(b)에 담으려 할 때는, 자동적으로 형 변환이 되지 않기 때문에 직접 형 변환을 선언해주어야 한다.

 

형 변환은 삽입되는 변수 앞에 (들어가질 더 큰 자료형)을 붙이면 된다. 위에서 i 앞에 (byte)를 붙인 것처럼 말이다.

 

만일 (byte)를 앞에 붙이지 않는다면 Type mismatch: cannot convert from int to byte라는 메세지와 함께 에러가 뜨며 프로그램을 실행할 수 없게 될 것이다.

 

더보기

💡  Java에서 쓰여지는 모든 정수의 기본형은 int, 실수의 기본형은 double이다.

 

사용자의 편의를 위해 byte b = 12;라고 해도 Java는 아무런 문제 없이 그것을 byte로 받아들이게 된다. 하지만 long에 12,345,678,910이라는 수를 넣으려 한다면 오류가 뜰 것이다. long의 범위 내에서 담을 수 있는 숫자인데도 말이다. 이는 12,345,678,910을 int로 인식하기에 생기는 문제이다.

 

따라서, long에 int 범위 이상의 값을 대입하려면 long에 대입한다는 표시로 숫자 뒤에 알파벳 L을 넣어줘야 한다. 이는 간단한 강제 형 변환이다. 소문자로 넣어줘도 문제가 없으나 숫자 1과 혼동 할 수 있으므로 대문자를 넣는 것이 좋다.

 

long l = 12345678910L;

 

실수형의 기본형이 double이기에 생기는 문제도 있다. 우리는 큰 범위의 변수를 작은 범위의 변수에 담으려면 강제 형 변환을 해야 한다고 했다. float라는 작은 범위의 변수에 큰 범위의 변수값인 double형의 실수를 넣을 수는 없다. 그래서 우리는 long의 경우와 마찬가지로, float의 값 뒤에 f를 붙여주어야 한다. 이 또한 대소문자 상관이 없다.

 

float f = 1.6f;

 

 

오버플로우(Overflow)

 

몇몇 독자는 궁금해 할지도 모르겠다.

 

그렇다면 특정 자료형 A의 범위 이상인 값을 자료형 B의 변수에 담고, 그 변수를 강제 형변환 하여 A에 대입했을 경우 어떻게 될까? 잘 들어갈까? 

 

그런 경우, 들어가긴 들어가지만 잘 들어가지는 않는다.

 

이게 무슨 말이냐면, 값이 들어가지기는 하나 손실되는 값이 생긴다는 것이다.

 

 

Copyright free image by Zac Harris

 

COMMENT