본문 바로가기
Study/JAVA

[Java] 2-5. 형변환

by jeongwle 2022. 8. 3.
728x90
반응형

1. 형변환(캐스팅, casting)

모든 변수와 리터럴에는 타입이 있다. 같은 타입 뿐만 아니라 서로 다른 타입간의 연산을 수행해야 하는 경우, 연산을 수행하기 전에 타입을 일치시켜야 한다. 이럴 때 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환(casting)이라 한다.

 

2. 형변환 방법

형변환 방법은 아주 간단하다. 형변환하고자 하는 변수나 리터럴의 앞에 변환하고자 하는 타입을 괄호와 함께 붙여주기만 하면 된다.
(타입)피연산자​

여기에 사용되는 괄호()는 캐스트 연산자 또는 형변환 연산자라고 하며 형변환을 캐스팅이라고도 한다.
double d = 85.4;
int score = (int)d; // double 타입의 변수 d를 int 타입으로 형변환

// 과정
int score = (int)d;
int score = (int)85.4;
int score = 85;​

위의 과정에서 보다시피 형변환 연산자는 그저 피연산자의 값을 읽어 지정된 타입으로 형변환하고 그 결과를 반환한다. 그래서 피연산자인 변수 d의 값은 형변환 후에도 아무런 변화가 없다.

기본형에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능하다. 그리고 기본형과 참조형간의 형변환은 불가능하다. 참조형의 형변환은 7장에서 설명한다고 한다.

 

3. 정수형간의 형변환

큰 타입에서 작은 타입으로의 변환, 예를 들어서 int타입(4byte)의 값을 byte타입(1 byte)으로 변환하는 경우 크기의 차이만큼 잘려나간다. 그래서 경우에 따라 값 손실(loss of data)이 발생할 수 있다. 반대로 작은 타입에서 큰 타입으로의 변환은 값 손실이 발생하지는 않는다. 그리고 나머지 빈 공간은 0 또는 1로 채워진다. 원래의 값을 채우고 남은 빈공간은 0으로 채우는게 보통이지만 변환하려는 값이 음수인 경우에는 빈 공간을 1로 채운다.

 

4. 실수형 간의 형변환

실수형도 마찬가지로 작은 타입에서 큰 타입으로 변환하는 경우 빈 공간을 0으로 채운다. float타입의 값을 double타입으로 변환하는 경우, 지수(E)는 float의 기저인 127을 뺀 후 double의 기저인 1023을 더해서 변환하고, 가수(M)는 float의 가수 23자리를 채우고 남은 자리를 0으로 채운다.
0 10000010 11111111111111111111111
0 10000000010 1111111111111111111111100000000000000000000000000000
반대로 double타입에서 float타입으로 변환하는 경우 지수(E)는 double의 기저인 1023을 뺀 후 float의 기저인 127을 더하고, 가수(M)는 double의 가수 52자리 중 23자리만 저장되고 나머지는 버려진다.
한가지 주의할 점은 가수 24번째 자리의 값이 1이라면 반올림이 발생해 23번째 자리의 값이 1 증가할 수 있다는 것이다.
음.. 사실 이렇게까지 알아야 하나 하는 생각이 들기도 하고 이렇게 한번 봐서는 잘 와닿지 않는 것 같다.

 

5. 정수형과 실수형 간의 형변환

정수형을 실수형으로 변환하는 것은 비교적 변환이 간단하다. 실수형은 정수형보다 큰 저장범위를 갖기 때문이다. 다만 실수형의 정밀도의 제한으로 인해 오차가 발생할 수 있다. int의 최대값은 약 20억으로 최대 10자리의 정밀도를 요구하지만 float은 약 7자리의 정밀도만을 제공하므로 8자리 이상의 값을 실수형으로 변환하고자 할 때는 double로 형변환해야 오차가 발생하지 않는다.

반대로 실수형을 정수형으로 변환하면 소수점 이하의 값은 버려진다. 정수형은 소수점 이하의 값을 표현할 수 없기 때문이다. 만일 실수의 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘는 경우에 오버플로우가 발생한 결과를 얻는다.

 

6. 자동 형변환

서로 다른 타입간의 대입이나 연산을 할 때, 타입을 일치시키는 것이 원칙이다. 하지만 편의상 생략하기도 하는 데 이 때 형변환이 일어나지 않는 것이 아니고 컴파일러가 생략된 형변환을 자동적으로 추가한다.
float f = 1234; // 형변환의 생략. float f = (float)1234; 와 같음​


하지만 변수가 저장할 수 있는 값보다 큰 값을 저장하려는 경우에 형변환을 생략하면 에러가 발생한다.
그러나 명시적으로 형변환을 한다면 실수가 아니라 의도적인 것으로 간주하고 컴파일러는 에러를 발생시키지 않는다.

byte b = 1000; // error

char ch = (char)1000; // 에러가 발생하지 않는다.


서로 다른 두 타입간의 덧셈에서는 두 타입 중 표현범위가 더 넓은 타입으로 자동으로 형변환하여 타입을 일치시킨 후 연산을 한다. 더 넓은 타입으로 형변환 하는 것이 값손실의 위험이 적어 올바른 결과를 얻어낼 확률이 높기 때문이다.

boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능하다.
기본형과 참조형은 서로 형변환할 수 없다.
서로 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있다.

 

728x90
반응형

'Study > JAVA' 카테고리의 다른 글

[Java] 3-2. 단항 연산자  (0) 2022.08.30
[Java] 3-1. 연산자  (0) 2022.08.30
[Java] 2-2. 변수의 타입  (0) 2022.08.02
[Java] 2-1. 변수(variable)  (0) 2022.08.02
[Java] Java의 정석  (0) 2022.08.01

댓글