2024. 12. 24. 14:38ㆍJAVA
안녕하세요. 진득 코딩입니다.
이제까지 변수와 리터럴, 그리고 여러 진법에 대해 살펴보았습니다.
변수에는 여러 타입들이 있는데 서로 다른 타입 간의 연산을 수행해야 하는 경우도 있습니다.
이럴 때는 연산을 수행하기 전에 타입을 일치시켜야 합니다.
이번 시간에는 변수나 리터럴의 타입을 다른 타입으로 변환하는 형변환(casting)에 대해서 알아보도록 하겠습니다.
형변환 하는 법
(타입) 피연산자
- 형변환을 하는 방법은 형변환하고자 하는 변수나 리터럴의 앞에 변환하고자 하는 타입을 괄호와 함께 붙여주기만 하면 됩니다.
- 여기에 사용되는 괄호()는 캐스트 연산자 또는 형변환 연산자라고 하며, 형변환을 캐스팅(casting)이라고도 합니다.
- 위 예제에서 형변환 연산자는 그저 피연산자의 값을 읽어서 지정된 타입으로 형변환하고 그 결과를 반환할 뿐입니다.
- 그래서 피연산자인 변수 d의 값은 형변환 후에도 아무런 변화가 없습니다.
- 기본형(primitive type)에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능합니다.
- 또한 기본형과 참조형간의 형변환은 불가능합니다.
변환 | 수식 | 결과 |
int -> char | (char)65 | 'A' |
char -> int | (int)'A' | 65 |
float -> int | (int)1.6f | 1 |
int -> float | (float)10 | 10.0f |
- float에서 int로 형변환할 때 반올림이 아닌 버림을 하는 것을 확인할 수 있습니다.
정수형간의 형변환
- 큰 타입에서 작은 타입으로의 변환하는 경우에는 크기의 차이만큼 잘려나간다.
- 그래서 경우에 따라 '값 손실(loss of data)이 발생할 수 있습니다.
- 반대로 작은 타입에서 큰 타입으로의 변환하는 경우는 저장공간의 부족으로 잘려나가는 일이 없으므로 값손실이 발생하지 않습니다.
- 나머지 빈공간은 0 또는 1로 채워진다.
- 보통 남은 빈공간은 0으로 채우지만 변환하려는 값이 음수인 경우에는 빈 공간을 1로 채우게 됩니다.
- 음수는 2의 보수법으로 이루어져 있기 때문에 형변환 후에도 부호를 유지할 수 있도록 하기 위해서입니다.
위 예제 처럼 'Integer.toBinaryString(int i)'라는 메서드를 이용하여 10진 정수를 2진 정수로 변환한 문자열을 얻을 수 있습니다.
실수형 간의 형변환
- 실수형에서 작은 타입에서 큰 타입으로 변환하는 경우, 빈 공간을 0으로 채웁니다.
- float타입의 값을 double 타입으로 변환하는 경우, 지수(E)는 float의 기저인 127을 뺀 후 double의 기저인 1023을 더해서 변환합니다.
- 가수(M)는 float의 가수 23자리를 채우고 남은 자리를 0으로 채웁니다.
- 반대로 double 차입에서 float타입으로 변환하는 경우, 지수(E)는 double의 기저인 1023을 밴 후 float의 기저인 127을 더합니다.
- 가수(M)는 double의 가수 52자리 중 23자리만 저장되고 나머지는 버려집니다.
- 이때 가수의 24번째 자리에서 반올림이 발생하여 23번째 자리의 값이 1 증가할 수 있습니다.
- 위와 같이 float 타입의 범위를 넘는 값을 float로 형변환하는 경우는 +-무한대 또는 +-0을 결과로 얻습니다.
- 위 예제를 보면 알 수 있듯이 float와 doouble이 서로 다른 자릿수에서 버리고 반올림하기 때문에 다른 값이 저장되게 됩니다.
- 이미 저장할 때 값이 달라졌기 때문에, 형변환을 해도 값이 같아지지 않습니다.
정수형을 실수형으로 변환
- 정수형과 실수형은 저장형식이 완전히 다르기 때문에 좀 더 복잡한 변환 과정을 거쳐야 합니다.
- 정수형을 실수형으로 변환할 때에는 그저 정수를 2진수로 변환한 다음 정규화를 거쳐 실수의 저장형식으로 저장됩니다.
- 실수형은 정수형보다 훨씬 큰 저장범위를 갖기 때문에, 정수형을 실수형으로 변환하는 것은 별 무리가 없습니다.
- 다만 실수형의 정밀도의 제한으로 인한 오차가 발생할 수 있습니다.
- 예를 들어 int의 최대값은 약 20억으로 최대 10자리의 정밀도를 요구합니다.
- 그러나 float는 10진수로 약 7자리의 정밀도만을 제공하므로, int를 float로 변환할 때 정밀도 차이에 의한 오차가 발생할 수 있습니다.
- 그러므로 10잔슗 8자리 이상의 값을 실수형으로 변환할 때는 float보다는 double을 사용하는 것이 바람직합니다.
실수형을 정수형으로 변환
- 실수형을 정수형으로 변환하면, 실수형의 소수점이하 값은 버려집니다.
- 또한 실수의 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘는 경우에는 정수의 오버플로우가 발생한 결과를 얻게 됩니다.
자동 형변환
- 서로 다른 타입간의 대입이나 연산을 할 때, 형 변환으로 타입을 일치시키는 것이 원칙입니다.
- 그러나 경우에 따라 편의상의 이유로 형변환을 생략할 수 있습니다.
- 이때 컴파일러가 생략된 형변환을 자동적으로 추가하는데 이를 자동 형변환이라고 합니다.
- 우변은 int 타입의 상수이고, 이 값을 저장하려는 변수의 타입은 float입니다.
- float 타입의 변수는 1234라는 값을 저장하는데 아무런 문제가 없기 때문에 자동 형변환이 됩니다.
- 하지만 위와 같이 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 저장하려는 경우에 형변환을 생략하면 에러가 발생합니다.
- 에러 메세지는 'incompatible types: possible lossy conversion from int to byte'인데, 큰 타입에서 작은 타입으로의 형 변환은 값 손실이 발생할 수 있다는 뜻입니다.
- 그러나 위와 같이 명시적으로 형변환 해줬을 경우, 형변환이 프로그래머의 의도라고 간주하고 컴파일러는 에러를 발생시키지 않습니다.
- 위와 같은 계산식에서 연산과정에서 형변환이 자동적으로 이루어집니다.
- 서로 다른 두 타입 간의 덧셈에서는 두 타입 중 표현범위가 더 넓은 타입으로 형변환하여 타입을 일치시킨 다음에 연산을 수행합니다.
- 표현범위가 더 넓은 타입으로 형변환하는 것이 값손실의 위험이 더 적어서 올바른 결과를 얻을 확률이 높기 때문입니다.
- 이처럼 연산과정에서 자동적으로 발생하는 형변환을 '산술 변환'이라고 합니다.
자동 형변환의 규칙
- 서로 다른 두 타입을 일치시리 때 컴파일러가 자동적으로 형변환을 하게 됩니다.
- 이때 컴파일러는 기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환합니다.
- 표현범위가 좁은 타입에서 넓은 타입으로 형변환하는 경우에는 값 손실이 없으므로 두 타입 중에서 표현범위가 더 넓은 쪽으로 형변환 됩니다.
- 위 그림에서 왼쪽에서 오른쪽으로의 변환은 형변환 연산자를 사용하지 않아도 자동 형변환이 되며, 그 반대 방향으로의 변환은 반드시 형변환 연산자를 사용해야 합니다.
- 보통 자료형의 크기가 큰 것일수록 표현범위가 크지만 실수형은 정수형과 값을 표현하는 방식이 다르기 때문에 같은 크기여도 실수형이 정수형보다 훨씬 더 큰 표현 범위를 갖기 때문에 float와 double이 같은 크기인 int와 long보다 오른쪽에 위치합니다.
- 이때 정수형을 실수형으로 형변환하는 경우에는 정밀도의 한계로 오차가 발생할 수 있으니 주의해야 합니다.
- char와 short은 둘 다 2byte의 크기로 크기가 같지만, char의 범위는 0~2^16-1(0~65535)이고 short의 범위는 -2^15~2^15-1(-32768~32767)이므로 서로 범위가 달라 둘 중 어느 쪽으로 형변환을 해도 값 손실이 발생할 수 있기 때문에 자동 형변환이 수행될 수 없습니다.
1. boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능합니다.
2. 기본형과 참조형은 서로 형변환할 수 없습니다.
3. 거솔 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있습니다.
이로서 형변환까지 모두 살펴보면서 변수에 대한 포스팅을 마치게 되었습니다.
변수라는 것은 자바를 하면서 기본중에 기본이지만 이 부분을 확실히 보고 가지 않으면 프로그래밍하면서 많은 의문점이 생길 거라고 생각합니다.
그래서 변수 파트에 있는 포스팅들을 잘 공부하시고 모르겠어도 한 번씩 읽어보고 넘어가는 것이 좋다고 생각합니다.
나중에 개발하면서 변수에 대한 의문점이 생기면 그때 다시 돌아와서 공부하시는 것도 좋은 방법이라고 생각합니다.
이번 포스팅은 여기까지입니다.
다음 포스팅은 다음 주제인 연산자(operator)에 대한 포스팅을 시작하도록 하겠습니다.
끝까지 봐주셔서 감사합니다.😊
'JAVA' 카테고리의 다른 글
자바 산술 연산자에 대해 알아보자 (2) | 2024.12.27 |
---|---|
자바 연산자(operator) 개념과 종류에 대해 알아보자 (0) | 2024.12.26 |
기본형 타입 중 정수형과 실수형에 대해 알아보자 (0) | 2024.12.23 |
기본형 타입 중 논리형과 문자형에 대해 알아보자 (4) | 2024.12.20 |
진법을 이용하여 숫자를 여러 방식으로 표현해보자 (0) | 2024.12.19 |