형변환이란?
변수 또는 상수의 타입을 다른 타입으로 전환하는 것을 의미한다.
자세히 설명하자면
프로그램을 작성하다보면 서로 다른 타입간의 연산을 수행해야하는 경우가 있다.
이럴 때는 연산을 수행하기 위해 타입을 일치시켜야 하는데,
변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환이라 한다.
형변환 방법은 아주 간단하다.
다음과 같이 변환하고자 하는 변수나 리터럴 앞에 변환하고자하는 타입을 괄호와 함께 적어주면 된다.
(타입)피연산자
예를 들어, 다음과 같은 코드가 있을 때,
변수의 변환과정은 다음과 같다.
double d = 14.3;
int a = (int)d; // double타입의 변수 d를 int타입으로 형변환
int a = (int)14.3; //변수 d의 값을 읽어 와서 형변환
int a = 14; //형변환의 결과인 14를 변수 a에 저장한다.
이 때의 변수 d의 값은 형변화 후에도 아무런 변화가 없다.
형변환은 기본형에서 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타입으로 변환할 때 소수점 이하의 값은 반올림이아닌,
버림으로 처리된다는 점을 주의하자.
정수형간의 형변환
큰 타입에서 작은 타입으로의 변환한다고 가정해보자.
예를 들어, int타입의 값을 byte타입으로 변환하는 경우 값 손실이 발생할 수 있다.
왜냐하면 int타입의 크기가 byte타입의 크기보다 크기 때문이다.
반대로 작은타입에서 큰 타입으로 변환한다고 가정해보자.
byte타입의 값을 int타입으로 변환한다고 하면
저장공간의 부족으로 잘려나가는 일은 발생하지 않으므로 값 손실이 발생하지 않는다.
다음 실습프로그램을 보면
값 손실이 발생한 경우와 그렇지 않은 경우를 자세히 살펴볼 수 있다.
정수형과 실수형 간의 형변환
먼저 정수형을 실수형으로 변환하는 것부터 살펴보자.
정수는 소수점이하의 값이 없으므로 비교적 변환이 간단하다.
실수형은 정수형보다 훨씬 큰 저장범위를 갖기 때문에,
정수형을 실수형으로 변환하는 것은 별 무리가 없다.
단, 한가지 주의할 점은 실수형의 정밀도의 제한으로 인한 오차가 발생할 수 있다.
예를 들어, int형의 최대값은 약 20억으로 최대 10자리의 정밀도를 요구하지만
float은 10진수로 약 7자리의 정밀도만 제공하므로, int를 float로 변환할 때
오차가 발생할 수 있다.
그래서 만일, 8자리 이상의 값을 실수형으로 변환할 때는 double로 형변환을 해야한다.
다음 예시를 살펴보자.
91234567 (float)-> 91234568.0 (int)-> 91234568
91234567 (double)-> 91234567.0 (int)-> 91234567
float은 정밀도가 약 7자리이므로 오차가 발생하는 것을 알 수 있지만,
double은 약 15자리의 정밀도를 갖기 때문에 오차없이 변환이 가능한 것을 알 수 있다.
다음 실수형을 정수형으로 변환하는 것을 살펴보자.
실수형을 정수형으로 변환하면, 실수형의 소수점이하 값은 버려진다.
왜냐하면 정수형의 표현형식으로 소수점 이하의 값은 표현할 수 없기 때문이다.
1.666 (int)-> 1
이렇게 말이다.
하지만 실수의 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘는 경우에는,
정수의 오버플로우가 발생한 결과를 얻는다.
다음 실습프로그램을 보면, 오차가 발생한 경우와 그렇지 않은 경우를 자세히 알 수 있다.
자동형변환
서로 다른 타입간의 대입이나 연산을 할 때,
형변환으로 타입을 일치시켜주는 것이 원칙이지만
경우에 따라 편의상의 이유로 형변환을 생략할 수 있다.
컴파일러가 생략된 형변환을 자동적으로 추가하는 것이다.
다음과 같은 문장을 봐보자.
float f = 123; //형변환의 생략. float f = (float)123; 과 같음
위의 문장에서 123은 int타입의 상수이고, 값을 저장하려는 변수의 타입은 float이다.
서로 타입이 달라서 형변환이 필요하지만 생략하였다.
float타입의 변수는 123이라는 값을 저장하는데 아무런 문제가 없기 때문이다.
그러나, 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 저장하려는 경우에는 에러가 발생한다.
byte b = 1000; //byte의 범위를 넘는 값을 저장. 에러발생
앞서 배운 것과 같이 큰 타입에서 작은 타입으로의 형변환은 값 손실이 발생하는 것과 같다.
하지만, 다음과 같이 명시적으로 형변환 해줬을 경우, 형변환이 프로그래머의 실수가 아닌
의도적인 것으로 간주하고 컴파일러는 에러를 발생시키지 않는다.
char ch = (char)1000; //명시적 형변환, 에러X
또 다른 예로, 연산 과정에서 자동적으로 발생하는 형변환인 '산술 변환'이 있다.
int i = 3;
double d = 1.0 + i; //double d = 1.0 + (double)i; 이 생략됨.
따라서
double d = 1.0 + 3.0; 이 수행됨.
여기서 자동 형변환의 규칙이 존재한다.
기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환을 하는 것인데,
표현범위가 좁은 타입에서 넓은 타입으로 형변환하는 경우에는 값 손실이 없으므로
두 타입 중에서 표현범위가 더 넓은 쪽으로 형변환된다.
byte -> short, char -> int -> long -> float -> double
화살표 방향으로의 변환, 즉 왼쪽에서 오른쪽으로의 변환은 형변환 연산자를 사용하지 않아도
자동 형변환이 되며, 그 반대 방향으로의 형변환은 반드시 형변환 연산자를 사용해야한다.
'JAVA > Basic' 카테고리의 다른 글
[JAVA-basic] 다차원 배열 (0) | 2021.08.09 |
---|---|
[JAVA-basic] String배열 (0) | 2021.08.06 |
[JAVA-basic] 배열 (0) | 2021.08.04 |
[JAVA-basic] 진법 (0) | 2021.07.27 |
[JAVA-basic] 변수와 상수 (0) | 2021.07.26 |