본문 바로가기
Programming

[Java의 정석] 제 2장 변수 - 3.형변환

by SyWORLD 2017. 6. 21.
반응형

** 단순히 공부를 위한 참고자료일 뿐입니다. **

** 현재 버전과 상이한 부분은 검색해주시길 바랍니다. **



3. 형변환

3.1. 형변환(Casting)이란?

모든 리터럴과 변수에는 타입이 있다는 것을 배웠습니다. 프로그램을 작성하다 보면, 서로 다른 타 입의 값으로 연산을 수행해야하는 경우가 자주 발생합니다.
모든 연산은 기본적으로 같은 타입의 피연산자(Operand)간에만 수행될 수 있으므로, 서로 다 른 타입의 피연산자간의 연산을 수행해야하는 경우, 연산을 수행하기 전에 형변환을 통해 같은 타입으로 변환해주어야 합니다.

예를 들어 int형 값과 float형 값의 덧셈연산을 수행하려면, 먼저 두 값을 같은 타입으로 변환해 야하므로, 둘 다 int형으로 변환하던가 또는 둘 다 float형으로 변환해야합니다.


3.2 형변환 방법

기본형과 참조형 모두 형변환이 가능하지만, 기본형과 참조형 사이에는 형변환이 성립되지 않습니다. 기본형은 기본형으로만 참조형은 참조형으로만 형변환이 가능합니다.

형변환 방법은 매우 간단하며 다음과 같습니다.

형변환이란, 변수 또는 리터럴의 타입을 다른 타입으로 변환하는 것이다.

(타입이름)피연산자

피연산자 앞에 변환하고자 하는 타입의 이름을 괄호에 넣어서 붙여 주기만 하면 됩니다. 여기에 사용되는 괄호는 특별히 캐스트연산자(형변환 연산자)라고 하며, 형변환을 캐스팅(Casting)이 라고도 합니다.
캐스트연산자는 수행결과로 피연산자의 값을 지정한 타입으로 변환하여 반환합니다. 이 때, 형변 환은 피연산자의 원래 값에는 아무런 영향도 미치지 않습니다.

[예제2-7] CastingEx1.java

class CastingEx1 {

public static void main(String[] args) {

double d = 100.0; int i = 100;
int result = i + (int)d;

System.out.println("d=" + d); System.out.println("i=" + i); System.out.println("result=" + result);

} }

[실행결과]

d=100.0 i=100 result=200

double변수 d와 int변수 i의 덧셈 연산을 하기 위해 캐스트연산자를 이용해서 d를 int형으로 변환하여 덧셈연산을 수행하였습다. 그리고 그 결과를 int변수 result에 저장하였습니다.
int형과 int형의 연산결과는 항상 int형 값을 결과로 얻으므로 result의 타입을 int형으로 하였습니다.

결 과의 첫째 줄을 보면 d=100.0으로 형변환 후에도 d에 저장된 값에는 변함이 없습니다. 캐스트 연산자를 이용해서 d를 형변환 하였어도 d에 저장된 값에는 변함이 없음을 알 수 있습니다. 단지, 형변환 한 결과를 덧셈에 사용했을 뿐입니다.

[참고]캐스트 연산자는 우선순위가 매우 높기 때문에 덧셈연산 전에 형변환이 수행되었습니다.


3.3 기본형의 형변환

8개의 기본형 중에서 boolean을 제외한 나머지 7개의 기본형 간에는 서로 형변환이 가능합니다.


[표2-10]기본형간의 형변환
[참고]char형은 십진수로 0~65535의 코드값을 갖는다. 문자 'A'의 코드는 십진수로 65입니다.

각 자료형 마다 표현할 수 있는 값의 범위가 다르기 때문에 범위가 큰 자료형에서 범위가 작은 자료형으로의 변환은 값 손실이 발생할 수 있습니다.
예를 들어 실수형을 정수형으로 변환하는 경우 소수점 이하의 값은 버려지게 됩니다. 위의 표에 서도 알 수 있듯이 float리터럴인 1.6f를 int로 변환하면 1이 됩니다.

반대로 범위가 작은 자료형에서 큰 자료형으로 변환하는 경우에는 절대로 값 손실이 발생하지 않으므로 변환에 아무런 문제가 없습니다.
[참고]실수형을 정수형으로 변환할 때 소수점 이하의 값은 반올림이 아닌 버림으로 처리된다는 점에 유의하도록 합시다.


[예제2-8] CastingEx2.java

  class CastingEx2 {

   public static void main(String[] args) {

      byte b = 10;
      int i = (int)b; System.out.println("i=" + i); System.out.println("b=" + b);

      int i2 = 300;
      byte b2 = (byte)i2; System.out.println("i2=" + i2); System.out.println("b2=" + b2);

    } 

  }

[실행결과]

i=10 b=10 i2=300 b2=44


byte 형 값을 int형으로, int형 값을 byte형으로 변환하고 그 결과를 출력하는 예제입니다. byte 와 int는 모두 정수형으로 각각 1 byte(8 bit)와 4 byte(32 bit)의 크기를 갖으며, 표현할 수 있
는 값의 범위는 byte가 -27 ~ 27-1(-128~127), int가 -232 ~ 232-1 입니다.

byte 의 범위를 int가 포함하고 있으며, int가 byte보다 훨씬 큰 표현 범위를 갖고 있습니다. 아래 그림에서 볼 수 있는 것과 같이 byte값을 int값으로 변환하는 것은 1 byte에서 4 byte로 나머지 3 byte(24자리)를 단순히 0으로 채워 주면 되므로 기존의 값이 그대로 보존됩니다.
하지만, 반대로 int값을 byte값으로 변환하는 int값의 상위 3 byte(24자리)를 잘라내서 1 byte로 만드는 것이므로 기존의 int값이 보존될 수도 있고 그렇지 않을 수도 있습니다.


[표2-10]byte와 int간의 형변환

원칙적으로는 모든 형변환에 캐스트연산자를 이용한 형변환이 이루어져야 하지만, 값의 표현 범위가 작은 자료형에서 큰 자료형의 변환은 값의 손실이 없으므로 캐스트 연산자를 생략할 수 있도록 했습니다.
그렇다고 해서 형변환이 이루어지지 않는 것은 아니고, 캐스트 연산자를 생략한 경우에도 JVM 의 내부에서 자동적으로 형변환이 수행됩니다.

반면에 값의 표현범위가 큰 자료형에서 작은 자료형으로의 변환은 값이 손실될 가능성이 있으 므로, JVM이 자동적으로 형변환하지 않고 프로그래머에게 캐스트 연산자를 이용하여 형변환 을 하도록 강요하고 있습니다.

위의 예제에서도 int i = (int)b;를 int i = b;와 같이 캐스트 연산자를 생략할 수 있으나 byte b2 = (byte)i2;에서는 캐스트 연산자를 생략해서 byte b2 = i2;와 같이 할 수 없습니다.
값의 표현범위가 큰 자료형에서 작은 자료형으로의 형변환에 캐스트 연산자를 사용하지 않으면 컴파일시 에러가 발생합니다.


[그림2-3]기본형의 자동형변환이 가능한 방향

위의 그림은 형변환이 가능한 7개의 기본형을 왼쪽부터 오른쪽으로 표현할 수 있는 값의 범위 가 작은 것부터 큰 것의 순서로 나열한 것입니다.
화살표방향으로의 변환, 즉 왼쪽에서 오른쪽으로의 변환은 캐스트 연산자를 사용하지 않아도 
자동형변환이 되는 변환이며, 그 반대 방향으로의 변환은 반드시 캐스트 연산자를 이용한 형변 환을 해야 합니다.

보 통 자료형의 크기가 큰 것일 수록 값의 표현범위가 크기 마련이지만, 실수형은 정수형과는 값을 표현하는 방식이 다르기 때문에 같은 크기일지라도 실수형이 정수형보다 훨씬 더 큰 표현 범위를 갖기 때문에 float와 double이 같은 크기인 int와 long보다 오른쪽에 위치합니다.

short과 char은 모두 2 byte의 크기를 갖지만, short의 범위는 -215 215-1(-32768~32767)이고 char의 범위는 0~216-1(0~65535)이므로 서로 범위가 달라서 둘 중 어느 쪽으로의 형변환도 값 손실이 발생할 수 있으므로 자동적으로 형변환이 수행될 수 없습니다.

위의 그림을 참고하여 형변환 시에 캐스트 연산자를 생략할 수 있는지 또는 캐스트 연산자를 사용해야하는지를 결정하도록 합니다.

<< 요약정리 >>

  1. boolean을 제외한 나머지 7개의 기본형들은 서로 형변환이 가능하다.
  2. 기본형과 참조형 간에는 서로 형변환이 되지 않는다.
  3. 서로 다른 타입의 변수간의 연산에는 형변환이 요구되지만, 값의 범위가 작은 타입에서

      큰 타입으로의 변환은 생략할 수 있다.










반응형

댓글