Language/Java

Java 형변환 - 명시적 형변환

괘창 2024. 7. 1. 22:52

■ 명시적 형변환

큰 범위에서 작은 범위 대입은 명시적 형변환이 필요하다.

 

#double 은 실수를 표현할 수 있다. 이에 따라 1.5 가 가능한데 int 는 실수를 표현할 수 없다.

  double을 int 로 대입하면 어떻게 될까?

 

 

예제 코드)

package casting;

public class Casting2 {
    public static void main(String[] args) {

        double doubleValue = 1.5;
        int intValue = 0;

//        intValue = doubleValue; //컴파일 오류 발생
        intValue = (int)doubleValue; // 형변환
        System.out.println(intValue); // 출력 : 1
    }
}

 

 

실행 결과)

# int 형은 double 형보다 숫자의 표현 범위가 작으며, 실수 표현이 불가하다.

  이 경우 숫자가 손실되는 문제가 발생할 수 있다.

   쉽게 설명하면 큰 컵에 담긴 물을 작은 컵에 옮겨 담으려고 하니 손실이 발생할 수 있는 것이다.


- 형변환

# 이런 위험을 개발자가 감수하고 값을 대입하고 싶다면 데이터 타입을 강제로 변경할 수 있다.

   예를들어 설명하면 대략적인 결과를 보고 싶은데, 이 때 소수점을 버리고 정수로만 보고싶을 수 있다.

 

# 형변환은 아래와 같이 변경하고 싶은 데이터 타입을 ( int ) 와 같이 괄호를 사용해서 명시적으로 입력하면 끝!

   >> intValue = (int)doubleValue; // 형변환

# 이를 형(타입)을 바꾼다고 하여 형변환이라 하며, 영어로는 캐스팅이라 한다.

   개발자가 직접 형변환 코드를 입력한다고 해서 명시적 형변환이라 한다.

 

※ 캐스팅 용어

    캐스팅은 영어 단어 cast 에서 유래 되었다. cast 는 금속이나 다른 물질을 녹여 특정한 형태나 모양을 만드는 과정 의미

 

- 명시적 형변환 과정

// doubleValue = 1.5
intValue = (int)doubleValue;
intValye = (int)1.5;  // doubleValue에 있는 값을 읽는다.
intValue = 1; // (int) 로 형변환 한다. intValue의 int 형인 숫자 1을 대입한다.

# 형변환을 한다고 하여 doubleValue 자체의 타입이 변경되거나 그 안에 있는 값이 변경되는 것은 아니다.

   doubleValue 에서 읽은 값을 형변환 하는 것이다. doubleValue 안에 있는 값은 1.5 그대로 유지!

   변수의 값은 대입연산자 ( = ) 를 사용해서 직접 대입할 때만 변경된다.


- 형변환과 오버플로우

# 형변환을 할 때 작은 숫자가 표현할 수 있는 범위를 넘어서면?

 

 

예제 코드)

package casting;

public class Casting3 {
    public static void main(String[] args) {
        long maxIntValue = 2147483647; // int 최고 값
        long maxIntOver = 2147483648L; // int 최고값 + 1(초과)
        int intValue = 0;

        intValue = (int)maxIntValue; //형변환
        System.out.println("maxIntValue casting = " + intValue);

        intValue = (int)maxIntOver; //형변환
        System.out.println("maxIntOver casting = " + intValue);
    }
}

 

 

실행 결과)

 

 

- 정상 범위
long maxIntValue = 2147483647 를 보면 int 로 표현할 수 있는 가장 큰 수를 입력했다.
이 경우 int 로 표현할 수 있는 범위에 포함되기 때문에 long >> int 로 형변환을 해도 문제가 없다.

- 수행 내용
intValue = (int)maxIntValue; // 형변환
maxIntValue = 2147483647; // int 최고값
intValue = (int)2147483647L; 형변환
intValue = 2147483647;

 

- 초과 범위
long maxIntOver = 2147483648L를 보면 int 로 표현할 수 있는 가장 큰 숫자보다 1큰 숫자를 입력했다.
이 숫자 리터럴은 int 범위를 넘어가기 때문에 L을 붙여 long 형을 사용해야 한다.
이 경우 int로 표현할 수 있는 범위를 넘기 때문에 long >> int 로 형변환 시 문제가 발생한다.

- 수행 내용
intValue = (int)maxIntOver; //형변환
maxIntOver = 2147483648L; // int 최고값 + 1
intValue = (int)maxIntOver; // 변수 값 읽기
intValue = (int)2147483648L; //형변환 시도
intValue = -214748648;

 

  • 결과 확인 시 -2147483648 이란 전혀 다른 수가 보인다.
    int 형은 2147483648L 을 표현할 수 있는 방법이 없어 기존 범위를 초과해서 표현하면 다른 숫자가 표현되며,
    이런 현상을 오버플로우라 한다.
  • 보통 오버플로우가 발생하면 마치 시계가 한 바퀴 돈 것 처럼 다시 처음부터 시작한다.
    -2147483648 숫자는 int 의 가장 작은 숫자이다.
  • 오버플로우가 발생하는 것이 문제이며, 오버플로우 발생 시 결과가 어떻게 되는지 계산하는데 시간 낭비되므로
    오버플로우가 발생하지 않도록 막아야 한다.
    이 경우 단순히 대입하는 변수 (intValue) 의 타입을 int > long 으로 변경하면 오버플로우 문제 해결!

 

long longValue = 0;
longValue = maxIntOver; //형변환
       System.out.println("maxIntOver casting = " + longValue);

# 이런식으로 오버플로우가 발생한 변수를 담을 수 있도록 더 큰 타입의 신규 변수 생성 필요