본문 바로가기
카테고리 없음

[Java] 당신이 빠뜨릴 수 있었던 사사로운 Java 지식들 1 - 형변환(자동 형변환 & 강제 형변환)

by 개발자만타 2023. 7. 23.

이미 Java 를 사용하던 유저이고, 그래도 나름 더닝 크루거 효과 그래프에서 "우매함의 봉우리" 에는 올라가 있다고 자신하고 있었던 저였습니다...만, 내일 Java 기본적인 평가를 본다 하여 정리를 하는 김에, Java 를 이미 하실 줄 아셨던 분들께서도 빠뜨릴 수 있는, 혹여나 제가 그냥 알지 못했던 지식들을 한번 정리해 볼까 합니다. 물론, 이미 아시고 계셨던 분들께서는 "쟤는 이런 것도 몰랐구나... ㅎ" 하면서 귀엽게 봐 주시길 부탁드립니다! ㅎㅎ

저는 더닝 크루거 그래프에서 우매함의 봉우리 에서 절망의 계곡으로 빠지기 직전이 아닐까 합니다.

1. 타입 변환(Type Conversion)

타입 변환, 혹은 형변환이라고도 불리는 파트입니다. 크게 두 가지 규칙이 있습니다.

1.1 자동 형변환

간단히 말해서, 작은 "범위" 에 있던 데이터를 큰 범위의 변수에 옮길 때, "강제 형변환" 을 진행하지 않아도 자동으로 형변환을 발생시켜준다는 규칙입니다. 마치, 작은 그릇에 있던 값을 큰 그릇에 옮길 때 자연스럽게 옮겨져 가는 것 처럼 되는 규칙입니다.

한마디로, 이런 것이 가능하다는 것입니다. 정수 변수 a를 그냥 b 에다 옮길 때, 아무 일 없었다는 듯이 바뀌는 것입니다.

int a = 10;
double b = a;

그런데, long 형은 8byte 이고 float 형은 4byte 인데, 어떻게 long 에서 float 형으로 자동 형변환이 일어나지?

확실히 이상해 보여서, 조금 자세히 들여다 보았습니다.

1.1.1 Long

long 의 범위는 -2^63 ~ 2^63 - 1 까지입니다. 정확히 표현해 보면, - 9223372036854775808 ~ 9223372036854775807 까지입니다. 대략 -922경 ~ 922 경 사이의 숫자 범위인 것입니다.

1.1.2. Float

float 의 범위는, 1.4E-45 ~ 3.4E38 (1.4×10^-45 ~ 3.4×10^38) 으로 정의되어 있습니다. float 의 범위는, 대략

-3.4 * 10^38 ~ 3.4 * 10^38 입니다. 단, -1.4 * 10^-45 ~ 1.4 * 10^-45 사이의 숫자는 float 의 범위에서 예외입니다.

long 의 최대값 922경을 지수와 가수 형태로 나타내 보면, 9.22 * 10^18 로 나타낼 수 있습니다. 10^38 제곱까지 나타낼 수 있는 float 범위가 더 넓다고 할 수 있습니다. 그래서 8byte 형태의 long 형은 float 로 나타낼 수 있는 것입니다. 물론, 당연히 8byte 의 숫자로 표현하던 것이 4byte 로 줄어들게 되므로, 일정 범위 이하의 숫자 데이터가 유실되는 것은 어쩔 수 없을 것입니다.

저도 헷갈렸던 것은, long 형은 2^63 - 1 까지 나타낼 수 있고, float 은 10^38 까지 나타낼 수 있어서 단순하게 지수만 보면 long 형이 더 큰것 아니야? 라고 생각할 수 있지만, 아닙니다 ^^ (제가 잠시 바보같이 이렇게 착각해서 적어둡니다.)

반대로, float 형을 long 형으로 나타내면 되는 것 아니냐고 생각할 수 있지만, 기본적으로 float 의 숫자 범위가 long 형보다 더 넓습니다. 그래서 long 형을 float 형으로 바꿀 때 자동 형변환이 적용되는 것이 더 합리적일 것 같습니다.

그럼 4byte 로 나타내는 float 은 어떻게 long 형보다 더 넓은 범위의 숫자를 표현하는 것일까?

바로 "부동소수점" 방식으로 숫자를 표현하기 때문에 가능한 것입니다.

부동소수점 방식으로 지수부와 가수부를 나누고, 가수부에는 실제 값을, 지수부에는 2제곱을 얼마나 곱할지 표현하기 때문에 수의 표현 범위가 long 타입보다 더 커지게 되는 것입니다. 물론, 당연히 long 타입이 해당 숫자를 더 정확히 나타낼 수는 있을 것입니다. 정수 범위 안이라면 말이죠!

 

하나 더 이상한 점?! 분명히 C 언어에서 char 의 크기는 1byte 이다. 그런데 Java 에서는 char 의 크기가 2byte?

무려 출처는 오라클이다. 이게 어떻게 된 일일까?

내가 눈이 잘못되어서 둘 중에 하나를 잘못 본 줄 알았습니다. 하지만, ssafy 에서 배우는 수업 자료는 분명히 65535 까지의 숫자로 나타낼 수 있다고 적혀 있습니다. 어찌 된 일일까요?

 

아래의 글에서 힌트를 얻을 수 있었습니다.

 

https://www.sololearn.com/Discuss/2134104/why-char-size-is-2-byte-in-java-while-it-take-1-byte-in-c

 

Why Char size is 2 Byte in Java ? while it take 1 byte in C | Sololearn: Learn to code for FREE!

Please Explain

www.sololearn.com

요약하자면, Java 에서는 유니코드 베이스, C 에서는 ASCII 코드 베이스로 문자를 나타내는데, 유니코드 베이스로 하는 Java char 는 18개의 언어를 지원하게 만들어졌기 때문에 256 정도의 크기로는 이를 수행할 수 없다는 내용이 있습니다.

충분히 설득력 있는 부분인 것 같습니다. 그렇지 않으면, 당장 Java 에서 한글 char 도 지원할 수 없을 것이기 때문이죠. 혹시 이에 대해서 더 자세하게 아시는 분은, 댓글 부탁드립니다!

2. 강제 형변환(Casting)

강제 형변환은 "명시적 형변환" 이라고 불리며, 사용자가 "타입 캐스트 연산자" (ex : (double)135 ) 를 사용해 값의 타입을 강제적으로 변환하는 것을 수행하는 것을 말합니다.

작은 범위의 타입은 큰 크기의 타입으로 자동 형변환이 가능하지만, 반대로 큰 범위의 타입은 작은 범위의 타입으로 자동 형변환을 수행할 수 없습니다. 그래서 "타입 캐스트 연산자" 를 붙여 주어야 한다는 것이죠.

int num = 200;
short shortValue = (short)num;

당연히 주의해야 하는 점은, 강제적인 동작이므로 데이터의 손실이 일어날 수 있다는 점입니다. 그리고 그에 따라, 연산 시 예상치 못한 결과를 얻을 수 있습니다.