자바의 타입 변환 메커니즘(타입 캐스팅)은 프로그래머가 한 타입의 값을 다른 타입으로 명확히 또는 암묵적으로 변환할 수 있게 해줍니다. 역사적으로 이 기능은 C와 C++에서 물려받았지만, 자바에서는 타입 안전성을 높이고 데이터 손실이나 오버플로우와 관련된 숨겨진 버그를 방지하기 위해 제한되어 있습니다.
문제는 참조 타입을 변환할 때 ClassCastException이 발생할 수 있는 가능성과, 예를 들어 double에서 int로 변환할 때의 정확성 손실입니다. 실제로 객체가 해당 클래스에 속하지 않는 경우, '다운 캐스팅'(하위 타입으로의 변환)에서 논리적 오류가 발생할 수 있습니다.
해결책은 엄격한 분리로 구성됩니다:
기본 타입에 대한 코드 예:
int i = 100; long l = i; // 암묵적 변환(int -> long) double d = l; // 암묵적 변환(long -> double) int i2 = (int) d; // 명시적 변환 (소수 부분 손실)
참조 타입에 대한 코드 예:
Object obj = "Hello"; // upcasting, 암묵적으로 String s = (String) obj; // downcasting, 명시적으로
주요 특징:
자바 컴파일러가 모든 잘못된 타입 변환을 방지할 수 있나요?
답변: 아니요, 컴파일러는 컴파일 단계에서 명백한 오류만 잡습니다. 타입 구조(예: Object -> String)에서 변환이 가능하지만, 변수에 실제로 호환되지 않는 타입의 객체가 있을 경우, 오류는 실행 중에 ClassCastException으로 나타납니다.
Integer는 Long에서 상속받나요, 그리고 Integer i = (Integer) someLong을 작성할 수 있나요?
답변: 아니요, Integer와 Long은 독립적인 래퍼 클래스이며, 이들 사이에서 다운 캐스팅을 할 수 없습니다. 둘 다 Number를 상속받지만 서로의 상속을 받지 않습니다. (Integer) (Object) 1L;와 같은 변환은 ClassCastException을 발생시킬 것입니다.
float를 int로 명시적으로 변환할 때 소수 부분이 반올림되나요?
답변: 아니요, 소수 부분이 반올림되지 않고 버려집니다:
float f = 3.99f; int i = (int) f; // i == 3, 4가 아님
개발자가 Object 컬렉션을 받아서 각 요소를 자신의 타입으로 변환하지만, instanceof 검사를 하지 않습니다. 잘못된 데이터로 인해 프로젝트가 ClassCastException으로 안정적으로 중단됩니다.
장점:
단점:
모든 다운 캐스팅 연산이 if (obj instanceof TargetType) 내부에서 명시적인 오류 처리를 통해 수행됩니다. 컬렉션에는 제너릭이 적용됩니다.
장점:
단점: