[JAVA] 형변환(casting)

PiggPotato·2023년 8월 1일
1

자바

목록 보기
6/7
post-thumbnail

💡 형변환?

변수 또는 상수의 타입을 다른 타입으로 변환하는 것을 말한다.

  • 서로 다른 타입간의 연산을 수행해야 하는경우, 연산을 수행하기 전에 타입을 일치시켜야 한다.
  • 서로 다른 타입 끼리의 값의 대입이나 연산은 불가능하기 때문이다. 이때 대입이나 연산이나 수행을 수행하기 전에 변수나 리터럴 타입을 다른 타입으로 변환하는 것을 형변환이라 한다,

💻 형변환 방법

형변환 하고자 하는 변수나 리터럴의 앞에 변환 하고자 하는 타입을 괄호()와 함께 붙여주면 된다.

  • 괄호() : '캐스트연산자' or '형변환연산자'라고 한다.
  • 피연산자에 저장된 값은 형변화 후에도 변화가 없다.
  • 그저 값을 읽어 지정된 타입으로 변환하고 결과를 반환하기 때문이다.
  • 기본형에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능하다.
  • 기본형과 참조형 간의 형변환은 불가능하다.

🤔 정수형간의 형변환

크기가 큰 타입에서 작은 터입으로의 변환

  • 크기의 차이만큼 잘려나간다.

  • 경우에 따라 값손실이 발생한다.

  • 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)27을 뺸 후 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이다.)

실수형 => 정수형

  • 실수형의 소수점 이하 값을 버려진다.
  • 반올림이 발생하지 않는다.
  • 정수형의 저장범위를 넘는 경우, 오버플로우가 발생한 결과를 얻는다,

🤔 형변환 안정장치

  • 자바에서 제공하는 모든 기본 타입에 대한 최대값과 최소값의 상수를 사용하여 형변환의 값 손실을 방지할 수 있다.
  • 상수를 활용하여 형변환 전 최소값과 최대값을 벗어나는지 검사를 하여 형변환을 할지 말지 선택하는 식으로 값 손실을 방지할 수 있다.
타입최대값 상수최소값 상수
byteByte.MAX_VALUEByte.MIN_VALUE
shortShort.MAX_VALUEShort.MIN_VALUE
shortShort.MAX_VALUEShort.MIN_VALUE
longLong.MAX_VALUELong.MIN_VALUE
floatFloat.MAX_VALUEFloat.MIN_VALUE
doubleDouble.MAX_VALUEDouble.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은 부동소수점 방식으로 표현을 하기 때문에 실제 표현 범위가 더 크기 때문이다.

💻 산술 변환

연산 전에 피연산자 타입의 일치를 위해 자동 형변환 된는 것을 '산술 변환' 또는 '일반 산술 변환'이라한다.

🤔 산술 변환의 규칙

1. 두 피연산자의 타입을 같게 일치 시킨다.(큰 타입으로 일치시킨다.)

- 피연산자의 값손실을 최소화 하기 위함

2. 피연산자의 타입이 int보다 작은 타입이면 int로 변환된다.

- 자바는 피연산자를 4byte 단위로 저장하기 때문에, 정수 연산일 경우 int 타입이 기본이기 때문이다.
  • 쉬프트 연산자와 증감 연산자에는 일어나지 않는다.
profile
초보 개발자 입니다.

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

좋은 글이네요. 공유해주셔서 감사합니다.

답글 달기