자바에서 변수 캐스팅


84

누가 캐스팅이 어떻게 작동하는지 말해 줄 수 있을까? 언제 해야하는지 이해 하지만 실제로 어떻게 작동하는지는 이해 하지 못합니다. 원시 데이터 유형에 대해서는 부분적으로 이해하지만 객체를 캐스팅 할 때는 작동 방식을 이해하지 못합니다.

Object 유형의 객체가 갑자기 MyType(예제 일뿐) 모든 메소드를 얻을 수있는 방법으로 갑자기 캐스트 될 수 있습니까?


제안 읽기 : 상속
프란체스코 Menzani

답변:


182

Java로 캐스팅하는 것은 마술이 아닙니다. 컴파일러에게 A 유형의 객체가 실제로 더 구체적인 유형 B라는 것을 알려주므로 그렇지 않으면 B의 모든 메소드에 액세스 할 수 있습니다. 캐스팅을 수행 할 때 어떤 종류의 마술이나 변환도 수행하지 않습니다. 기본적으로 컴파일러에게 "저를 믿으세요. 제가하는 일을 알고 있습니다.이 줄에있는이 개체가 실제로 <Insert cast"라는 것을 보장 할 수 있습니다. 여기에 입력>. " 예를 들면 :

Object o = "str";
String str = (String)o;

위의 내용은 괜찮습니다. 마술이 아닙니다. o에 저장되는 객체는 실제로 문자열이므로 문제없이 문자열로 캐스팅 할 수 있습니다.

이것이 잘못 될 수있는 두 가지 방법이 있습니다. 첫째, 완전히 다른 상속 계층 구조에서 두 유형간에 캐스팅하는 경우 컴파일러는 사용자가 어리 석다는 것을 알고 중지합니다.

String o = "str";
Integer str = (Integer)o; //Compilation fails here

둘째, 동일한 계층 구조에 있지만 여전히 유효하지 않은 캐스트 인 경우 ClassCastException런타임에 a 가 발생합니다.

Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here

이것은 본질적으로 컴파일러의 신뢰를 위반했음을 의미합니다. 개체가 특정 유형임을 보장 할 수 있다고 말했지만 그렇지 않습니다.

왜 캐스팅이 필요한가요? 글쎄, 시작하려면 더 일반적인 유형에서 더 구체적인 유형으로 이동할 때만 필요합니다. 예, 들어 Integer로부터 상속 Number, 그래서 당신이를 저장하려면 IntegerA와 Number그의 확인 (모든 정수는 숫자이기 때문에.) 그러나, 당신이 캐스트가 필요 둘레에 다른 길을 갈려면 - (모든 숫자가 정수하지뿐만 아니라 우리가 정수로 Double, Float, Byte, Long, 등) 프로젝트 또는 JDK에서 하나 개의 서브 클래스가있다 그리고 경우에도, 누군가가 쉽게 보장을했습니다 없다, 그래서 당신이 하나의 당연한 선택이라고 생각하더라도, 다른를 작성하고 배포 할 수 !

캐스팅에 대한 사용과 관련하여 일부 라이브러리에서 여전히 필요합니다. Java-5 이전에는 모든 컬렉션이 개체를 추가 한 다음 컬렉션에서 다시 가져온 결과를 캐스팅하기 때문에 컬렉션 및 기타 다양한 클래스에서 많이 사용되었습니다. 그러나 제네릭의 출현으로 캐스팅에 대한 많은 사용이 사라졌습니다. ClassCastExceptions의 가능성없이 훨씬 안전한 대안을 제공하는 제네릭으로 대체되었습니다 (사실 제네릭을 깨끗하게 사용하고 경고없이 컴파일하는 경우, ClassCastException이 발생하지 않을 것이라는 보장이 있습니다.)


설명해 주셔서 감사합니다. 내가 이것을 이해한다면 아마도 나는 그렇지 않을 것입니다. 객체를 캐스트 할 때 컴파일러 에게이 메모리 주소의 객체가 이러한 메소드 등에 응답하는 방법을 안다는 것을 컴파일러에게 알리는 것이므로 나를 거부하지 마십시오. 그 맞습니까?
user626912 2011 년

1
@ user626912 종류-메모리 주소 측면에서 생각하지 마십시오. 컴파일러에게 주어진 객체가 인터페이스를 따르고 따라서 주어진 메소드의 구현을 가지고 있다고 말하는 것이 아닙니다 (동일한 메소드로 완전히 다른 객체를 만들 수 있으며 캐스팅이 반드시 작동하지는 않습니다.) 컴파일러에게 다음과 같이 말하고 있습니다. 한 유형의 객체는 실제로 더 구체적인 유형이므로 더 구체적인 객체에서 사용할 수있는 메서드를 사용할 수 있습니다. 아직 읽지 않았다면 다형성에 대해 읽어보십시오. 좀 더 명확하게 만드는 데 도움이 될 수 있습니다.
Michael Berry

"더 일반적인 유형에서 더 구체적인 유형으로 이동할 때만 필요하다"는 말은 의심 스럽습니다. ((Object) gpsLastLoc.getLatitude ()). getClass (). getSimpleName ()은 런타임에 "double"이름을 반환하며 이는보다 구체적인 유형에서보다 일반적인 유형으로 캐스트하는 예제 사용입니다.
Fruit

1
@ 林果 皞이 경우 기본 형식을 홍보하기 위해 캐스팅을 사용하고 있습니다. 이것은 좀 더 일반적인 유형으로 이동하는 것과는 다르며 작업을 수행하는 매우 이상한 방법입니다. 더 일반적인 (더 나은) 방법은 Double.valueOf(gpsLastLoc.getLatitude()).getClass().getSimpleName(). 두 경우 모두 기본 클래스를 동적으로 가져올 필요가 없습니다 getLatitude(). 이중 기본 형식을 반환하면 항상 Double개체 로 승격 될 것임을 알고 있기 때문 입니다.
Michael Berry

나는 코드가 "컴파일러의 신뢰를 위반"했다는 당신의 말이 마음에 듭니다. (시. 오타가 있습니다. "you 've"대신 "you 're"라고 썼습니다.)
Jason L.

7

실제로 캐스팅이 항상 작동하는 것은 아닙니다. 객체가 instanceof캐스팅하는 클래스 가 아닌 경우 ClassCastException런타임에을 얻습니다 .


5

a String를 a 로 캐스트하고 싶다고 가정합니다 File(예, 말이되지 않습니다), File클래스가 자식이 아니고 클래스의 부모가 아니기 때문에 직접 캐스트 할 수 없습니다 String(컴파일러가 불평합니다).

그러나 당신은 당신의 캐스팅 수 String에를 ObjectA가 있기 때문에, String입니다 Object( Object부모). 그런 다음 File파일이 Object.

따라서 모든 작업은 컴파일 타임에 타이핑 관점에서 '합법적'이지만 런타임에 작동한다는 의미는 아닙니다!

File f = (File)(Object) "Stupid cast";

컴파일러는 이해가되지 않더라도이를 허용하지만 다음 예외와 함께 런타임에 충돌이 발생합니다.

Exception in thread "main" java.lang.ClassCastException:
    java.lang.String cannot be cast to java.io.File

3

참조 캐스팅은 instanceof해당 유형 인 경우에만 작동합니다 . 무작위 참조를 캐스트 할 수 없습니다. 또한 Casting Objects.

예 :

String string = "String";

Object object = string; // Perfectly fine since String is an Object

String newString = (String)object; // This only works because the `reference` object is pointing to a valid String object.

3

올바른 방법은 다음과 같습니다.

Integer i = Integer.class.cast(obj);

이 메서드 cast()는 컴파일 타임 캐스팅보다 훨씬 안전한 대안입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.