Java 형 변환 (Type Casting)

소개 (Introduction)

형 변환(Typecasting)은 값을 한 유형에서 다른 유형으로 변환하는 기술입니다. 이 글에서는 자바에서의 형 변환, 그 유형, 그리고 자바 프로그래밍 언어에서 제공되는 메서드 및 생성자에 대해 배워보겠습니다.

자바에서의 형 변환이란 무엇인가?

자바에서 한 데이터 유형의 값을 다른 데이터 유형에 할당할 때 두 유형이 호환되지 않을 수 있습니다. 데이터 유형이 호환되면 자바는 자동으로 변환을 수행하며 이를 자동 변환이라고 합니다. 형 변환은 자바에서 형 변환(Type Conversion)으로도 알려져 있습니다. 이것은 공평하게 이루어지지만 때로는 오류가 발생할 수 있습니다.

형 변환은 종종 메서드가 필요한 형태와 다른 형식의 데이터를 반환할 때 필요합니다.

특정 상황에서는 형 변환이 자동으로 이루어질 수 있으며, 다른 경우에는 수동으로 이루어져야 합니다(명시적 형 변환).

예를 들어, int 값을 long 변수에 할당하는 것입니다.

Syntax

데이터유형 변수명 = (데이터유형) 변환할변수;

자바에서의 형 변환 구문

형 변환을 하려면 목표 유형을 괄호 안에 지정하고 그 뒤에 변수 이름 또는 변환할 값을 지정해야 합니다. 다음 명령문 예시를 참고하세요.

Syntax

int 숫자;
float 값 = 32.33;
숫자 = (int) 값;

자바에서의 형 변환 유형 (Types of Type Casting in Java)

1) 암시적 형 변환(Implicit Typecasting) 및 명시적 형 변환(Explicit Typecasting)
2) 업 캐스팅(Up-casting) 및 다운 캐스팅(Down-casting)
3) 자동 박싱(Autoboxing) 및 언박싱(Unboxing)

1) 암시적 형 변환(Implicit Typecasting) 및 명시적 형 변환(Explicit Typecasting)

암시적 형 변환(Implicit Typecasting) in Java

넓히는 형 변환이라고도 하는 자동 형 변환은 두 데이터 유형이 서로 호환되는 경우 자동으로 변환되는 경우가 발생합니다. 작은 범위의 유형과 큰 범위의 유형을 형 변환하는 것을 넓히는 형 변환(Widening Typecasting)이라고 합니다.

작은 유형에서 큰 유형 크기로 형 변환하는 것입니다.

  • byte -> short -> char -> int -> long -> float -> double

두 데이터 유형은 호환됩니다.
더 작은 데이터 유형의 값을 더 큰 데이터 유형에 할당할 때
대상 유형이 소스 유형보다 큽니다.
예를 들어, 자바에서 숫자 데이터 유형은 호환됩니다. 그러나 숫자 형식에서 char 또는 boolean으로의 자동 변환이 지원되지 않습니다. 또한 char와 boolean은 서로 호환되지 않습니다.

암시적 형 변환은 또한 넓히는 형 변환(Widening Typecasting) 및 자동 형 변환(Automatic Type Conversion)이라고도 합니다.

다음은 넓히는 형 변환(Widening Typecasting)에 대한 완전한 프로그램입니다.

public class TypeCasting {
    public static void main(String[] args) {
        int 숫자 = 10;
        float 소수점 = 숫자;
        System.out.println(숫자);
        System.out.println(소수점);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

10
10.0

정수 및 부동 소수점 유형, 포함하여 정수 및 부동 소수점 유형은 서로 호환됩니다.

참고: 자동 형 변환은 모든 요구 사항을 충족하지는 못합니다. 예를 들어, float 값을 바이트 변수에 할당하려는 경우 어떻게 할까요? 이러한 변환이 자동으로 수행되지 않습니다. 왜냐하면 바이트가 float보다 작기 때문입니다. 이러한 형 변환은 목표 유형에 맞추기 위해 값을 명시적으로 더 좁게 만드는 것이기 때문에 때로 명시적 형 변환(narrowing conversion)이라고도 부릅니다.

float에서 int로의 자바 형 변환

float에서 int로의 형 변환의 완전한 프로그램은 다음과 같습니다.

public class TypeCasting 1 {
    public static void main(String[] args) {
        int 숫자;
        float fval = 32.33f;
        숫자 = (int) fval;
        System.out.println(숫자);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

32

int에서 float로의 자바 형 변환

int와 float는 각각 4바이트의 메모리를사용합니다. int는 정수를, float는 부동 소수점 숫자를 보유합니다. int를 float로 할당하는 것은 JVM에 의해 자동으로 수행됩니다.

public class IntToFloatExample {
    public static void main(String args[])
    {
        int i1 = 10;
        float f1 = i1;
        System.out.println("int 값: " + i1);
        System.out.println("변환된 float 값: " + f1);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

int 값: 10
변환된 float 값: 10.0

double에서 int로의 자바 형 변환

double에서 int로의 형 변환의 완전한 프로그램은 다음과 같습니다.

public class DoubletoInt{
    public static void main(String[] args){
        System.out.println((int)1.87);
        System.out.println((double)1 / 2);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

1
0.5

int에서 double로의 자바 형 변환

int에서 double로의 형 변환의 완전한 프로그램은 다음과 같습니다.

public class IntToDoubleExample {
    public static main(String args[]) {
        int i = 200;
        double d = i;
        System.out.println(d);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

200.0

double에서 byte로의 자바 형 변환

double에서 byte로의 형 변환의 완전한 프로그램은 다음과 같습니다.

public class DoubleTOByteExample {
    public static main(String args[])
    {
        double d1 = 10.5;
        byte b1 = d1;  //컴파일 오류
        byte b1 = (byte) d1;  //컴파일 오류
        System.out.println("\ndouble 값: " + d1);
        System.out.println("변환된 byte 값: " + b1 );
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
    Type mismatch: cannot convert from double to byte
    Duplicate local variable b1

참고: double을 byte로의 자바 형 변환을 시도할 때 암시적으로 변환하면 오류가 발생하며, 바이트 데이터 유형은 1바이트의 메모리를 사용하고 double은 8바이트의 메모리를 사용합니다. 8바이트의 메모리를 1바이트의 메모리에 할당하려면 명시적인 캐스팅이 필요합니다.

byte에서 double로의 자바 형 변환

byte에서 double로의 형 변환의 완전한 프로그램은 다음과 같습니다.

public class ByteToDoubleExample {
    public static main(String args[]) {
        byte b1 = 10;
        double d1 = b1;
        System.out.println("byte 값: " + b1);
        System.out.println("변환된 double 값: " + d1);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

byte 값: 10
변환된 double 값: 10.0

자동 형 변환의 완전한 프로그램은 다음과 같이 나열되어 있으며 이 프로그램에서 캐스팅이 자동으로 수행됩니다.

public class ImplicitConversionExample {
    public static main(String args[]) {
        byte i = 50;
        // 아래 변환에 대해 캐스팅이 필요하지 않음
        short j = i;
        int k = j;
        long l = k;
        float m = l;
        double n = m;

        System.out.println("byte 값 : " + i);
        System.out.println("short 값 : " + j);
        System.out.println("int 값 : " + k);
        System.out.println("long 값 : " + l);
        System.out.println("float 값 : " + m);
        System.out.println("double 값 : " + n);
    }
}

위 프로그램은 다음과 같은 결과를 생성합니다.

byte 값 : 50
short 값 : 50
int 값 : 50
long 값 : 50
float 값 : 50.0
double 값 : 50.0

자바에서 클래스 유형의 암시적 캐스팅

작은 유형을 큰 유형에 할당할 때 캐스팅이 필요하지 않습니다. 클래스 유형에도 동일하게 적용됩니다. 전체 프로그램은 아래에 나와 있습니다.

class Parent {
    public void disp() {
        System.out.println("Parent disp called");
    }
}

public class TypeCasting  extends Parent {
    // 하위 클래스
    public static void main(String args[]) {
        Parent p = new TypeCasting  ();
        p.disp();
    }
}

위 프로그램은 다음 출력을 생성합니다.

Parent disp called

자바에서 명시적 타입 캐스팅

데이터의 한 유형이 다른 유형의 변수에 할당될 때 다음 두 조건이 충족되면 좁은 유형 변환이 발생합니다.

  1. 대상 유형이 원본 유형보다 작아야 합니다.
  2. 이 두 조건이 충족되면 좁은 변환이 발생합니다. 예를 들어, int는 모든 유효한 double 값 모두를 보유하기에는 충분하지 않으므로 명시적인 캐스트 문이 필요합니다.

작은 유형에서 큰 유형 크기로의 형 변환:

  • byte -> short -> char -> int -> long -> float -> double

수치 유형에서 char 또는 boolean으로의 자동 변환은 없습니다. 또한 char와 boolean은 호환되지 않습니다.

명시적 캐스팅은 좁은 캐스팅으로도 알려져 있습니다.

public class TypeCasting  {
    public static void main(String[] args) {
        float point = 10.5f;
        int a = f; // 컴파일 타임 오류
        int number = (int) point;
        System.out.println(point);
        System.out.println(point);
    }
}

위 프로그램은 컴파일 타임 오류를 생성합니다.

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    f cannot be resolved to a variable

좁은 타입 캐스팅의 전체 프로그램은 아래에 나와 있습니다.

public class TypeCasting  {
    public static void main(String[] args) {
        float point = 10.5f;
        int number = (int) point;
        System.out.println(point);
        System.out.println(number);
    }
}

위 프로그램은 다음 출력을 생성합니다.

10.5
10

참고: 정수는 소수 부분이 없음을 알고 계실 것입니다. 따라서 부동 소수점 값이 정수 유형에 할당될 때 소수 부분이 손실됩니다. 예를 들어, 값 45.12가 정수에 할당되면 결과 값은 45가 됩니다. 0.12는 삭제됩니다.

전체 프로그램은 아래에 나와 있습니다.

public class TypeCasting  {
    public static void main(String[] args) {
        int number = 150;
        byte b = (byte) number;
        System.out.println(number);
        System.out.println(b);
    }
}

위 프로그램은 다음 출력을 생성합니다.

150
-106

전체 프로그램은 아래에 나와 있습니다.

public class TypeCasting  {
    public static void main(String[] args) {
        byte r = 10;
        byte s = 10;
        byte c = r + s; // 컴파일 타임 오류: r + s = 20은 int가 됨
        System.out.println(c);
    }
}

위 프로그램은 컴파일 타임 오류를 생성합니다.

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Type mismatch: cannot convert from int to byte

전체 프로그램은 아래에 나와 있습니다.

public class TypeCasting  {
    public static void main(String[] args) {
        byte r = 10;
        byte s = 10;
        byte c = (byte) (r + s);
        System.out.println(c);
    }
}

위 프로그램은 다음 출력을 생성합니다.

20

자바에서 double을 byte로 변환

우리는 알고 있듯이 자바에서 double을 byte로 암시적으로 변환하려고 하면 오류가 발생합니다. 바이트 데이터 유형은 1바이트의 메모리를 사용하고 double은 8바이트의 메모리를 사용합니다. 8바이트의 메모리를 1바이트의 메모리에 할당하려면 명시적으로 캐스팅이 필요합니다.

double을 byte로 변환하는 전체 프로그램은 아래에 나와 있습니다.

public class DoubleToByteExplicitConversion {
    public static void main(String args[]) {
        double d1 = 10.5;
        byte b1 = (byte) d1;
        System.out.println("\ndouble value: " + d1);
        System.out.println("Converted byte value: " + b1);
    }
}

위 프로그램은 다음 출력을 생성합니다.

double value: 10.5
Converted byte value: 10

자바에서 클래스 유형의 명시적 타입 캐스팅

큰 유형을 작은 유형에 할당할 때 명시적으로 캐스트해야 합니다. 전체 프로그램은 아래에 나와 있습니다.

class Parent {
    public void disp() {
        System.out.println("Parent disp called");
    }
}

public class Child extends Parent {
    // 하위 클래스
    public void disp() {
        System.out.println("Child disp called");
    }

    public static void main(String args[]) {
        Parent p = new Child();
        p.disp();
        Child c = p;
        c.disp();
    }
}

참고: 위의 코드를 실행하면 “Type mismatch: cannot convert from Parent to Child”라는 예외가 발생합니다.

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Type mismatch: cannot convert from Parent to Child

이를 수정하려면 코드를 아래에 나와 있는 대로 Child 클래스로 캐스트해야 합니다.

class Parent {
    public void disp() {
        System.out.println("Parent disp called");
    }
}

public class Child extends Parent {
    // 하위 클래스
    public void disp() {
        System.out.println("Child disp called");
    }

    public static void main(String args[]) {
        Child p = new Child();
        p.disp();
        Child c = p;
        c.disp();
    }
}

위 프로그램은 다음 출력을 생성합니다.

Child disp called
Child disp called

상위 캐스팅 및 하위 캐스팅

상위 캐스팅 (Upcasting)

상위 캐스팅은 상속 트리를 올라가서 하위 유형을 상위 유형으로 캐스팅하는 것을 의미합니다. 상위 캐스팅은 필수는 아닙니다. 그러나 우리가 상위 유형만 다루는 일반 코드를 작성하려면 상위 캐스팅이 필요합니다. 전체 상위 캐스팅 프로그램은 아래에 나와 있습니다.

class Super {
    // 상위 클래스
    void Sample() {
        System.out.println("super class의 메서드");
    }
}

public class TypecastingExample extends Super {
    // 하위 클래스
    void Sample() {
        System.out.println("하위 클래스의 메서드");
    }
    public static void main(String args[]) {
        Super obj = (Super) new TypecastingExample();
        obj.Sample();
    }
}

위 프로그램은 다음 출력을 생성합니다.

하위 클래스의 메서드

참고: 캐스팅으로 인해 실제 객체 유형은 변경되지 않습니다. TypecastingExample 객체는 여전히 TypecastingExample 객체입니다. 참조 유형만 변경됩니다.

하위 캐스팅 (Downcasting)

하위 캐스팅은 상속 트리를 내려가서 상위 유형을 하위 유형으로 캐스팅하는 것을 의미합니다. 실제 객체 유형이 대상 객체 유형과 일치하지 않으면 하위 캐스팅은 실패할 수 있습니다. 하위 캐스팅은 상위 캐스팅보다 더 자주 사용됩니다. 우리가 하위 유형의 특정 동작에 액세스하려면 하위 캐스팅을 사용합니다. 전체 하위 캐스팅 프로그램은 아래에 나와 있습니다.

class Super1 {
    void Sample() {
        System.out.println("상위 클래스의 메서드");
    }
}

public class TypecastingExample extends Super1 {
    void Sample() {
        System.out.println("하위 클래스의 메서드");
    }
    public static void main(String args[]) {
        Super1 obj = new TypecastingExample();
        TypecastingExample sub = (TypecastingExample) obj;
        sub.Sample();
    }
}

위 프로그램은 다음 출력을 생성합니다.

하위 클래스의 메서드

오토박싱과 언박싱

오토박싱 (Autoboxing)

오토박싱은 기본 유형 변수를 해당 래퍼 클래스 객체로 자동으로 변환하는 것을 의미합니다. 컴파일러는 기본값이 래퍼 클래스 객체를 기대하는 함수에 인수로 전달되거나 래퍼 클래스의 유형과 일치하는 변수에 할당될 때 변환을 자동으로 처리합니다. 전체 오토박싱 프로그램은 아래에 나와 있습니다.

import java.util.ArrayList;
import java.util.List;

public class TypecastingExample {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            // 인수로 전달하면 오토박싱
            // 컴파일러가 컴파일 중에 int 값을 Integer로 변환
            list.add(i);
        }

        System.out.println(list);
        char c = 'a';
        // Character 객체로 할당하면 오토박싱
        Character ch = c;
        System.out.println(ch);
    }
}

위 프로그램은 다음 출력을 생성합니다.

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a

언박싱 (Unboxing)

래퍼 클래스 유형의 객체를 해당 기본값으로 변환하는 것을 언박싱이라고 합니다. 예를 들어, Integer에서 int로 변환하는 것입니다. 자바컴파일러는 래퍼 클래스의 유형과 해당 기본 유형 값을 예상하는 메서드에 매개변수로 전달되거나 해당 기본 유형과 일치하는 변수에 할당될 때 언박싱을 적용합니다. 전체 언박싱 프로그램은 아래에 나와 있습니다.

public class TypecastingExample {
    public static void main(String[] args) {
        Integer integer = new Integer(-10);
        int i = abs(integer);
        System.out.println(i);

        int j = integer;
        System.out.println(j);
    }

    private static int abs(int i) {
        return (i < 0) ? -i : i;
    }
}

위 프로그램은 다음 출력을 생성합니다.

10
-10

요약

이 글에서는 자바에서의 타입 캐스팅 또는 변환과 예제를 알아보았으며 예제를 통해 자바 프로그래밍 언어에서의 타입 캐스팅을 어떻게 사용하는지 살펴보았습니다.

Leave a Comment