ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Chapter 2 - 형 변환(Casting)
    IT 공부 독서 정리/Java의 정석 2026. 1. 4. 15:18

    5. 1 형변환(Type Casting)이란?

    • 변수에는 저장할 데이터의 종류에 따라 타입(type) 이 존재한다.
    • 프로그램을 작성하다 보면
      같은 타입의 데이터뿐 아니라, 서로 다른 타입의 데이터 간 연산이 필요한 경우가 많다.
    • 서로 다른 타입의 데이터를 바로 연산하면
      오류가 발생하거나 원하지 않는 결과가 나올 수 있다.
    • 따라서 연산을 수행하기 전에
      데이터의 타입을 동일하게 맞추는 과정이 필요하다.
    • 이처럼 변수나 리터럴의 타입을 다른 타입으로 변환하는 과정
      👉 형변환(Type Casting) 이라고 한다.

    5.2 형 변환 방법

    • 형변환의 방법은 매우 간단하다.
    • 변환할 변수 앞에 변환하고자 하는 타입을 () 안에 작성하면 된다.
    • 형변환의 기본 형태는 다음과 같다.
    (타입) 피연산자
    • 예시:(Long) data;

    캐스트 연산자(Cast Operator)

    • 형변환에 사용되는 괄호 ()를
      캐스트 연산자 또는 형 변환 연산자라고 한다.
    • 형변환을 영어로 캐스팅(Casting) 이라고 한다.

    형변환 사용 예시

    double d = 85.4;
    int score = (int) d;
    • 위 코드는 다음과 같은 과정으로 수행된다.
    int score = (int) d;
    int score = (int) 85.4;
    int score = 85;

     

    형변환의 결과

    • 형변환 연산자는 피연산자의 값을 읽어서 지정한 타입으로 변환할 뿐이다.
    • 따라서, 처음 저장된 d의 타입은 아무런 변화가 없다.

    형변환 예제 코드는 아래와 같다.

     

    ▼ 예제 2-12 / ch2 / CastingEx2.java

    package ch5;
    
    public class Casting {
        public void Ex1() {
            double d = 85.4;
            int score = (int) d;
    
            System.out.println("score="+score);
            System.out.println("d="+d);
        }
    }

     

    ▼ 실행 결과

    더보기

    score = 85
    d=85.4   <- 형변환 후에도 피연산자에는 아무런 변화가 없다.

    기본형(primitive type)에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능 그리고 기본형과 참조형간의 형변환은 불가능하다. (간단한 예로 String에서 int로 변환하거나 String에서 int로 변환할 때에는 ()의 방법으로는 형변환이 불가능하다.)

    5.3 정수형 간의 형변환

     

    • 큰 타입에서 작은 타입으로 형변환을 수행하면 명시적 캐스팅이 필요하다.
    • 변환 시 작은 타입이 표현할 수 있는 범위까지만 값이 유지된다.
    • 표현 범위를 초과한 상위 비트는 잘려나간다(truncation).
    • 이로 인해 원래 값과 다른 결과가 저장될 수 있다.
    • 즉, 변환하는 값의 크기에 따라 값 손실(data loss)이 발생할 수 있다.
    • 자바 컴파일러는 이러한 손실 가능성 때문에 자동 형변환을 허용하지 않는다.

     

    큰 타입에서 작은 타입으로 변환

    변환 2진수 10진수 값손실
    int -> byte 00000000000000000000000000001010
                                                            00001010
    10
    10
    없음
    int -> byte 00000000000000000000000100101100
                                                           00101100
    300
    44
    있음

     

    작은 타입에서 큰 타입으로 변환 

    변환 2진수 10진수 값손실
    byte -> int                                                        00001010
    00000000000000000000000000001010
    10
    10
    없음
    byte -> int                                                         11111110
    00000000000000000000000011111110
    -2
    -2
    없음

     

    ▼ 예제 2-13 / ch2 / CastingEx2.java

    package ch2;
    
    public class CastingEx2 {
        public void Ex2() {
            int i = 10;
            byte b = (byte) i;
            System.out.printf("[int -> byte] i=%d -> b=%d\n", i, b);
    
            i = 300;
            b = (byte) i;
            System.out.printf("[int -> byte] i=%d -> b=%d\n", i, b);
    
            b = 10;
            i = (int) b;
            System.out.printf("[int -> byte] i=%d -> b=%d\n", i, b);
    
            b = -2;
            i = (int) b;
            System.out.printf("[int -> byte] i=%d -> b=%d\n", i, b);
    
            System.out.println("i="+Integer.toBinaryString(i));
        }
    }

     

    ▼ 실행 결과

    더보기

    [int -> byte] i=10 -> b=10
    [int -> byte] i=300 -> b=44
    [int -> byte] i=10 -> b=10
    [int -> byte] i=-2 -> b=-2
    i=11111111111111111111111111111110


    5.4 실수형 간의 형변환

    실수형에서도 정수형처럼 작은 타입에서 큰 타입으로 변환하는 경우 빈공간을 0으로 채우는 방식은 동일하다.


    Float → Double

    • 지수(E) : float의 기저인 127을 뺀 후 double의 기저인 1023을 더해서 변환
    • 가수(M) : float의 가수 23자리를 채우고 남은 자리를 0으로 채움


    Double → Float

    • 지수(E) : double의 기저인 1023을 뺀 후 float의 기저인 127을 더함
    • 가수(M) : double의 가수 52자리 중 23자리만 저장되고 나머지는 버려짐
      • 가수의 24번째 자리에서 반올림이 발생 할 수 있음(24번째 자리의 값이 1인 경우 1 증가)
      • float의 타입의 범위를 넘는 값을 float로 형변환 하는 경우 :  or 
      • double, float는 저장될 때 값이 달라지기 때문에 형변환을 해도 값이 같아지지는 않음


    아래 코드는 실수형간의 형변환 예제 코드이다.

     

    package ch2;
    
    public class CastingEx3 {
        public void Ex3() {
            float f = 9.1234567f;
            double d = 9.1234567;
            double d2 = (double) f;
    
            System.out.printf("f =%20.18f\n", f);
            System.out.printf("d =%20.18f\n", d);
            System.out.printf("d2=%20.18f\n", d2);
        }
    }

     

    ▼ 실행 결과

    더보기

    f =9.123456954956055000
    d =9.123456700000000000
    d2=9.123456954956055000

    위 결과를 보면 f와 d는 같은 값을 저장했지만, 실제로 저장되는 값은 다르다.

    변수 f에 저장된 값을 double타입으로 형변환해도 값은 그대로다. 

    위와 같은 일이 벌어지는것은 float가 저장하는 값의 정밀도와 double가 저장하는 값의 정밀도가 다르기 때문이다.

     

    float형인 f의 경우 값이 처음 값이 저장되면, 9.123456954956054700으로 저장되지만, double 형인 d의 경우 9.123456700000000200으로 저장된다.

     

    이미 저장을 할때부터 저장되는 값의 정밀도가 다르게 저장이 되버리기 때문에.. 이후 형변환을 한다고 하여 값이 같아지진 않는다.

     


    5.5 정수형과 실수형 간의 형변환

    우선 정수형과 실수형의 저장방식은 float와 doule간이 차이와는 비교할 수 없을정도로 완전히 다르기 때문에, 정수형간의 변환처럼 값을 자르는 식으로는 변환을 할 수 없다.

     


    정수형에서 실수형으로 변환

    • 정수는 소수점이하 값이 없으므로 비교적 변환이 간단
    • 정수를 2진수로 변환한 다음 정규화를 거쳐 실수의 저장형식으로 저장 될 뿐
    • 아래느 10진수 7을 float의 변수에 저장되는 과정을 보여줌

    • 실수형은 정수형보다 훨씬 큰 저장범위를 갖기 때문에, 정수형을 실수형으로의 변환은 별 문제 없이 변환된다.
    • 정수를 2진수로 변환한 다음에, 정규화해서 실수의 저장형식에 맞게 저장한다.
    • 다만 실수형의 정밀도로 인해 오차가 발생할 수는 있다.
    • 정수형의 최대값은 20억으로 10자리의 정밀도를 요구하지만, float는 10진수로 약 7자리의 정밀도만 제공하여 이로 인해 값이 달라짐
    • 따라서, 8자리 이상의 값을 변환하기 위해서는 float보단 double로 변환해야 값의 오차가 없다.


    실수형에서 정수형으로 변환

    • 실수형에서 정수형으로 변환을 하게 되면, 소수점 이하값들은 다 버려진다.
    • 정수형의 표현 형식으로 소수점 이하를 표현할 수 없기 때문이다.
    • float 9.1234567를 int로 변환하면 9가 된다.
    • 중요한것은 반올림이 아니라 모두 버려진다는 것
    • 또한, 실수형의 모든 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘기게 되면, 오버플로우가 발생하게 된다.
    package ch2;
    
    public class CastingEx4 {
        public void Ex4() {
            int     i = 91234567;
            float   f = (float) i;
            int     i2 = (int) f;
    
            double  d = (double) i;
            int     i3 = (int) d;
    
            float   f2 = 1.666f;
            int     i4 = (int) f2;
    
            System.out.printf("i=%d\n" ,i);
            System.out.printf("f=%f i2=%d\n" ,f, i2);
            System.out.printf("d=%f i3=%d\n" ,d, i3);
            System.out.printf("(int) %f=%d\n", f2, i4);
        }
    }

     

    ▼ 실행 결과

    더보기

    i=91234567
    f=91234568.000000 i2=91234568
    d=91234567.000000 i3=91234567
    (int) 1.666000=1


    5.6 자동 형변환

    • 앞장에서는 형변환이 무엇인지에 대한 개념과 형변환을 하기 위한 방법들을 설명했다.
    • 같은 형식 안에서는 범위가 다른 형변환과 변수형식이 전혀 다른 변수간의 형변환.
    • 이번 장에서는 자동 형변환에 대한 내용을 다룬다.
    • 서로 다른 타입간의 대입이나 연산 과정에서 형변환을 일치시키는것이 원익이지만, 때로는 생랴괴는 경우가 있다.
    • 형변환이 이루어지지 않는 것이 아니고, 컴파일러가 생략된 형변환을 자동적으로 추가한다.
    float f = 1234; // 형변환 생략. float f = (float)1234; 와 같음
    • 위에서는 우변은 int타입이고, 좌변은 float이다. 서로 타입이 달라서 형변환이 필요하지만 생략했다.
    • float형의 경우 1234 값을 저장하는데에는 아무 문제가 없기 때문이다.
    byte b = 1000; // 에러. byte의 범위 (-128 ~ 127)를 넘는 값 저장
    // imcompatible types :  possible lossy conversion from int to byte
    • 위 에러 메시지는 큰 타입에서 작은 타입으로는 형변환이 불가능하다는 메시지이다.
    • 형변환 자체가 불가능하지는 않지만, 값손실을 우려하여 컴파일러에서 미리 에러라고 지정한 것이다.
    char ch = (char) 1000; // 명시적 형변환. 에러 발생 X
    • 그러나 위에서처럼 (char)과 같이 명시적으로 형변환을 하여 작은타입으로 변환을 하면 에러가 발생하지 않는다.
    • 개발하는 개발자가 해당 사항에 대해서 염두하고 변환한다는것을 알고 있기 때문이다.
    int i = 3;
    double d = 1.0 + i; // double d = 1.0 + (double) i;에서 형변환이 생략됨
    • 서로 다른 두 타입간의 덧셈에서는 두 타입중 표현범위가 넓은 타입으로 자동 형변환을 하여 연산을 수행한다.
    • 이유는 큰 타입으로 변환 후 계산하는것이 값손실의 위험이 적기 때문이다.
    • 이처럼 산술 계산에서 자동으로 형변환이 되는것을 '산술 변환' 이라고 한다.

    자동 형변환 규칙

    자동 형변환을 하는 컴파일러는 어떤 기준으로 형변환을 하는것인가?

    • 표현 범위로치면, 좁은 타입에서 넓은 타입으로 현변환을 한다. (값손실이 없기 때문)

    • 위 방향과 반대인 형변환이 꼭 필요한 경우는 명시적으로 형변환을 한다는 표현을 반드시 작성해야 한다.
    • boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능함.
    • 기본형과 참조형간의 형변화는 불가능
    • 서로 다른 타입의 변수간의 연산은 형변환을 하는것이 원칙이지만, 값의 범위가 작은타입에서 큰 타입으로의 형변환은 생략 가능
Designed by Tistory.