본문 바로가기

Java

[Java] 자동 형변환? 캐스팅?

작은 범위에서 큰 범위로는 당연히 값을 넣을 수 있습니다.

예시 ) int → long → double

 

큰 범위에서 작은 범위로 값을 넘기게 되면 이런 문제들이 발생할 수 있죠?

1) 소수점 버림

2) 오버플로우

 

자바에서도 작은 범위에서 큰 범위로 대입은 허용합니다.

int < long < double

 

int 보다는 long이, long보다는 double이 더 큰 범위를 표현할 수 있습니다.

 

자바는 기본적으로 같은 타입에 값을 대입할 수 있습니다.

그런데 다른 타입에 값을 대입하면 어떻게 될까요?

 

int → long을 비교해보면 long이 int보다 더 큰 숫자 범위를 표현합니다.

작은 범위 숫자 타입에서 큰 범위 숫자 타입에 대입을 하면 문제가 되지 않습니다.

 

long → double의 경우에도 double은 부동 소수점을 사용하기 때문에 더 큰 숫자 범위를 표현합니다.

따라서 대입할 수 있습니다.

 

작은 범위에서 큰 범위로의 대입은 자바 언어에서 허용합니다.

큰 그릇은 작은 그릇에 담긴 내용물을 담을 수 있습니다. 사진 처럼 말이죠.

 

하지만 결국 대입하는 형(타입)을 맞추어야 하기 때문에 개념적으로는 다음과 같이 동작합니다.

intValue = 10
doubleValue = intValue
doubleValue = (double) intValue //형 맞추기
doubleValue = (double) 10 //변수 값 읽기
doubleValue = 10.0 //형 변환

 

이렇게 앞에 (double) 과 같이 적어주면 int 형이 double 형으로 형이 변한다. 이렇게 형이 변경되는 것을 형변환이라 한다.

작은 범위 숫자 타입에서 큰 범위 숫자 타입으로의 대입은 개발자가 이렇게 직접 형변환을 하지 않아도 된다.

이런 과정이 자동으로 일어나기 때문에 자동 형변환, 또는 묵시적 형변환이라고 한다.

 

그렇다면 작은 그릇에 큰 그릇을 넣게 된다면 어떻게 될까요?

 

이번에는 큰 범위에서 작은 범위로 대입해봅시다.

큰 범위에서 작은 범위 대입은 명시적 형변환이 필요합니다.

 

double은 실수를 표현할 수 있습니다. 따라서 1.5가 가능합니다.

그런데 int는 실수를 표현할 수 없습니다.

 

이 경우 double → int로 대입하면 어떻게 될까요?

 

int 형은 double 형보다 숫자가 표현 범위가 작습니다. 그리고 실수를 표현할 수도 없습니다.

따라서 이 경우 숫자가 손실되는 문제가 발생할 수 있습니다. 

쉽게 말해 큰 컵에 담긴물을 작은 컵에 옮겨 담으려고 하니, 손실이 발생할 수 있다는 것입니다.

이런 문제는 매우 큰 버그를 유발할 수 있습니다. 예를 들어 은행 프로그램 이자 계산같은 경우 말이죠.

 

하지만 만약 이런 위험을 개발자가 직접 감수하고도 값을 대입하고 싶다면 데이터 타입을 강제로 변경할 수 잇습니다.

예를 들어서 대략적인 결과를 보고 싶은데, 이때 소수점을 버리고 정수로만 보고 싶을 때 같은 상황에서 말이죠.

 

형변환은 다음과 같이 변경하고 싶은 데이터 타입을 (int)와 같이 괄호를 사용해서 명시적으로 입력하면 됩니다.

intValue = (int) doubleValue; //형변환

 

이것을 형(타입)을 바꾼다고 해서 형변환이라고 합니다. 영어로는 캐스팅이라 합니다.

그리고 개발자가 직접 형변환 코드를 입력한다고 해서 명시적 형변환이라고도 합니다.

 

//doubleValue = 1.5
intValue = (int) doubleValue; 
intValue = (int) 1.5; //doubleValue에 있는 값을 읽는다.
intValue = 1; //(int)로 형변환 한다. intValue에 int형인 숫자 1을 대입한다.

 

형변환 후 출력해보면 숫자 1이 출력되는 것을 확인할 수 있습니다.

참고로 형변환을 한다고 해서 doubleValue 자체의 타입이 변경되거나 그 안에 있는 값이 변경되는 것은 아닙니다.

doubleValue에서 읽은 값을 형변환 하는 것입니다. doubleValue 안에 들어있는 값은 1.5 그대로 유지됩니다.

참고로 변수의 값은 대입연산자 ( = )를 사용해서 직접 대입할 때만 변경됩니다.

 

이번에는 형변환을 할 때 만약 작은 숫자가 표현할 수 있는 범위를 넘어서면 어떻게 될까요?

 

long maxIntValue = 2147483647를 보면 int로 표현할 수 있는 가장 큰 숫자인 2147483647를 입력했다.

이 경우 int로 표현할 수 있는 범위에 포함되기 떄문에 다음과 같이 long → int로 형변환을 해도 아무런 문제가 없다.

 

결과를 보면 - 2147483648 이라는 전혀 다른 숫자가 보입니다. 

int형은 2147483648L을 표현할 수 있는 방법이 없습니다.

이렇게 기존 범위를 초과해서 표현하게 되면 전혀 다른숫자가 표현되는데, 이런 현상은 오버플로우라고 한다.

maxIntOver = 2147483648; //int 최고값 초과
intValue = (int) maxIntOver; //변수값 읽기
intValue = (int) 2147483648 //형변환 시도
intValue = -2147483648;

 

보통 오버플로우가 발생하면 마치 시계가 한바퀴 돈 것처럼 다시 처음부터 시작합니다.

중요한 것은 오버플로우가 발생하는 것 자체가 문제라는 점입니다.

 

오버플로우가 발생했을 때 결과가 어떻게 되는지 계산하는데 시간을 낭비하면 안됩니다.

오버플로우 자체가 발생하지 않도록 막아야하고, 이 경우 단순히 대입하는 변수(intValue)의 타입을

int long으로 변경해서 사이즈를 늘리면 오버플로우 문제가 해결되겠죠?

 

이런 오버플로우 문제는 자바에서 계산에서도 나타나는데요

 

1. 같은 타입끼리의 계산은 같은 타입의 결과를 나타낸다.

int + int는 int를 ,double + double은 double의 결과가 나온다.

 

2. 서로 다른 타입의 계산은 큰 범위로 자동 형변환이 일어난다.

int + long은 long + long 으로 자동 형변환이 일어난다.

int + double은 double + double로 자동 형변환이 일어나게 됩니다.

 

예시를 통해서 이해해봅시다.

 

 

'Java' 카테고리의 다른 글

[Java] 배열 이래도 이해가 안된다고?  (0) 2024.02.15
[Java] Scanner  (1) 2024.02.14
[Java] 지역 변수, scope 그게 뭔데?  (0) 2024.02.07
[Java] 자바 별찍기  (0) 2024.02.06
자바의 기초 Hello java 출력해보자!  (1) 2023.12.17