형변환?
변수 또는 상수의 타입을 다른 타입으로 변환하는 것을 말한다.
- 서로 다른 타입간의 연산을 수행해야 하는 경우, 연산을 수행하기 전에 타입을 일치시켜야 한다.
- 서로 다른 타입 끼리의 값의 대입이나 연산은 불가능하기 때문이다.
- 이때 대입이나 연산이나 수행을 수행하기 전에 변수나 리터럴 타입을 다른 타입으로 변환하는 것을 형변환이라 한다,
강제 형변환
형변환 하고자 하는 변수나 리터럴의 앞에 변환 하고자 하는 타입을 괄호()와 함께 붙여주면 된다.
int intValue = 103029770;
byte byteValue = (byte)intValue;
// 괄호() : '캐스트연산자' or '형변환연산자'라고 한다.
- 피연산자에 저장된 값은 형변화 후에도 변화가 없다. 그저 값을 읽어 지정된 타입으로 변환하고 결과를 반환하기 때문이다.
- 기본형에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능하다.
- 기본형과 참조형 간의 형변환은 불가능하다.
- .MAX_VALUE와 .MIN_VALUE로 각 타입의 최대, 최소값과 비교해 값의 손실이 발생하지 않도록 해야한다.
정수형간의 형변환
크기가 큰 타입에서 작은 타입으로의 형변환
- 크기의 차이만큼 잘려나가 경우에 따라 값손실이 발생한다.
- int => byte의 경우로, 300이었던 값이 값손실로 인해 44가 되었다.
크기가 작은 타입에서 큰 타입으로의 형변환
- 양수일 경우 나머지 공간을 0으로 채운다.
- 음수일 경우 1로 채운다.
- 값손실이 발생하지 않는다.
실수형 간의 형변환
크기가 큰 타입에서 작은 터입으로의 변환
- double => float
- 지수(E) : 기저(bias) 1023을 뺸 후 float의 기저인 127을 더한다.
- 가수(M) : 52자리 중 23자리만 저장하고 나머지는 버려진다. 52자리중 24번째 자리값이 1이면 반올림 발생, 23번째 자리가 1 증가한다.
크기가 작은 타입에서 큰타입으로의 형변환
- float => double
- 빈공간을 0으로 채운다.
- 지수(E) : 기저(bias)127을 뺸 후 double의 기저인 1023을더한다.
- 가수(M) : 23자리를 채운뒤, 남은 자리를 0으로 채운다.
float의 범위을 넘는 값을 float으로 변환
- ± 무한대 or ±0을 결과값으로 갖는다.
- 최대값보다 크면 ±무한대
- 최소값보다 작으면 ±0이다.
- 지수의 범위(-127~ 128)중 -127과 128은 숫자가 아니다. (NaN)이나 양/음의 무한대(POSITIVE/NEGATIVE_INFINITY)와 같이 특별한 값의 표현을 위해 예약되어 있기 때문이다.
float과 double에 같은 값을 저장
- 저장 방식의 차이에 의해 같은 값을 저장 하더라도 실제로 저장되는 값이 다르다.(정밀도)
- 저장 방식의 차이에 의해 float의 가수는 23자리 까지만을 저장하고, double은 가수를 52자리 까지 저장하기 때문에 같은 소수라도 저장하는 과정에서 버려지는 부분이 발생한다.
- 저장할 때 값이 달라졌기 때문에 저장후에 형변환을 해도 값이 같아지지 않는다.
정수형과 실수형 간의 형변환
- 저장 방식이 완전히 다르기 때문에 복잡한 변환 과정을 거쳐야 한다.
정수형 => 실수형
- 정수를 2진수로 변환한다음 정규화를 거쳐 실수형의 저장 형식으로 저장된다.
- 소수정 이하의 값이 없으므로 비교적 변환이 간단하다.
- 실수형은 정수형보다 훨씬 큰 저장 범위를 갖기 떄문이다.
실수형의 정밀도 제한으로 인한 오차가 발생할 수 있다.
- int는 최대값이 약 20억으로 정밀도가 10자리인데 flaot은 약 7자리이다. 정밀도가 차이가 나기 때문에 큰값을 저장하면 오차가 발생할 수 있다.
- float의 가수 23 bit로 표현가능한 값일경우 오차없이 표현 가능하다.(정밀도가 7이다)
- double은 가수부가 52bit로 할당되어 있어 8자리 이상은 double형을 사용함으로 오차 발생을 해결할 수 있다. (정밀도가 15이다.)
실수형 => 정수형
- 실수형의 소수점 이하 값을 버려진다.
- 반올림이 발생하지 않는다.
- 정수형의 저장범위를 넘는 경우, 오버플로우가 발생한 결과를 얻는다,
형변환 안정장치
- 자바에서 제공하는 모든 기본 타입에 대한 최대값과 최소값의 상수를 사용하여 형변환의 값 손실을 방지할 수 있다.
- 상수를 활용하여 형변환 전 최소값과 최대값을 벗어나는지 검사를 하여 형변환을 할지 말지 선택하는 식으로 값 손실을 방지할 수 있다.
타입 | 최대값 상수 | 최소값 상수 |
byte | Byte.MAX_VALUE | Byte.MIN_VALUE |
short | Short.MAX_VALUE | Short.MIN_VALUE |
short | Short.MAX_VALUE | Short.MIN_VALUE |
long | Long.MAX_VALUE | Long.MIN_VALUE |
float | Float.MAX_VALUE | Float.MIN_VALUE |
double | Double.MAX_VALUE | Double.MIN_VALUE |
int i = 128;
if( (i < Long.MIN_VALUE) || (i > Long.MAX_VALUE) ) {
System.out.println("Long타입의 범위를 넘어가는 값 입니다.");
} else {
long b = (long) i;
System.out.println(l);
}
자동 형변환
- 서로 다른 타입간 대입/연신을 할때 형변환으로 타입을 일치 시키는 것이 원칙이만 경우에 따라 생략이 가능하다.
- 컴파일러가 생략된 형변환을 독자적으로 추가한다.
- 작은 크기를 가지는 타입이 큰 크기를 가지는 타입에 저장될 경우에만 발생한다.
float f = 1234 // 변수의 타입은 float(실수), 리터럴의 타입은 int(정수)
자동 형변환시 에러?
- 범위보다 더 큰 값을 저장할 때 형변환이 생략할 경우 에러가 발생한다.
byte b = 1000 // 값 손실 발생 가능
- 명시적으로 형변환시 프로그래머의 의도한 것으로 간주하고 에러가 발생하지 않는다.
char ch = (char)1000 // 명시적 형변환
- 서로 다른 두 타입의 연산, 자동 형변환이 발생하여 타입을 일치 시킨뒤 연산을 수행하므로 에러가 발생하지 않는다.
int i = 3;
double d = 1.0 + i; // 1,0 + (double)i;
// 두 타입중 표현 볌위가 넓은 타입으로 타입을 일치시킨다.
컴파일러는 어떤 기준으로 타입을 일치시킬까?
기존의 값을 최대한 보존할 수 있는 타입으로 타입으로 자동 형변환한다.
- 범위가 좁은 타입에서 넓은 타입으로 형변환 하는 경우 값 손실이 없기 때문이다.
- 왼쪽에서 오른쪽(=>)으로의 변환은 형변환 연산자를 사용하지 않아도 자동 형변환이 되지만, 반대 방향(<=)으로의 형변환은 형변환 연산자(타입)를 사용해야 한다.
- char에 short/byte를 형변환하여 저장할 수는 없다, 크기가 같거나 작지만 서포 표현 범위가 다르기 때문에(char은 음수를 표현할 수 없다) 값 손실이 발생할 수 있기 때문에 자동 형변환이 수행될 수 없다.
- 실수형은 정수형과 값을 표현하는 방식이 다르기 때문에 같은 크기라도 실수형이 더 큰 표현 범위를 갖기 때문에 오른쪽에 위치한다.
- float은 4byte고 long은 8byte지만 float은 부동소수점 방식으로 표현을 하기 때문에 실제 표현 범위가 더 크기 때문이다.
산술 변환
연산 전에 피연산자 타입의 일치를 위해 자동 형변환 된는 것을 '산술 변환' 또는 '일반 산술 변환'이라한다.
산술 변환의 규칙
- 두 피연산자의 타입을 같게 일치 시킨다.(큰 타입으로 일치시킨다.)
- 피연산자의 값손실을 최소화 하기 위함
- 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.
- 자바는 피연산자를 4byte 단위로 저장하기 때문에, 정수 연산일 경우 int 타입이 기본이기 때문이다.
- 쉬프트 연산자와 증감 연산자에는 일어나지 않는다.
'Java' 카테고리의 다른 글
[JAVA] 조건문과 반복문 (0) | 2023.08.13 |
---|---|
[JAVA] 연산자(operator) (0) | 2023.08.05 |
[JAVA] 자바의 리터럴(literal)? (0) | 2023.08.05 |
[JAVA] 변수(variable)의 기본형과 참조형 (0) | 2023.08.05 |
[JAVA] 변수(variable)와 상수(constant) (0) | 2023.08.05 |