자바에서의 다운캐스트
Java에서는 업캐스팅이 허용되지만 다운캐스팅에서는 컴파일 오류가 발생합니다.
컴파일 오류는 캐스트를 추가하여 제거할 수 있지만 실행 시 중단됩니다.
이 경우 Java가 런타임에 실행할 수 없는 경우 다운캐스팅을 허용하는 이유는 무엇입니까?
이 컨셉에 실용성이 있나요?
public class demo {
public static void main(String a[]) {
B b = (B) new A(); // compiles with the cast,
// but runtime exception - java.lang.ClassCastException
}
}
class A {
public void draw() {
System.out.println("1");
}
public void draw1() {
System.out.println("2");
}
}
class B extends A {
public void draw() {
System.out.println("3");
}
public void draw2() {
System.out.println("4");
}
}
다운캐스팅은 런타임에 성공할 가능성이 있는 경우 허용됩니다.
Object o = getSomeObject(),
String s = (String) o; // this is allowed because o could reference a String
경우에 따라서는 성공하지 못할 수 있습니다.
Object o = new Object();
String s = (String) o; // this will fail at runtime, because o doesn't reference a String
런타임에 캐스트(마지막 캐스트 등)가 실패하면가 느려집니다.
그 외의 경우는, 다음과 같이 동작합니다.
Object o = "a String";
String s = (String) o; // this will work, since o references a String
일부 캐스트는 전혀 성공하지 못하기 때문에 컴파일 시 허용되지 않습니다.
Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.
예를 들어 다음과 같은 작업을 수행할 수 있습니다.
public void doit(A a) {
if(a instanceof B) {
// needs to cast to B to access draw2 which isn't present in A
// note that this is probably not a good OO-design, but that would
// be out-of-scope for this discussion :)
((B)a).draw2();
}
a.draw();
}
이것은 모든 정적으로 입력된 언어에 해당한다고 생각합니다.
String s = "some string";
Object o = s; // ok
String x = o; // gives compile-time error, o is not neccessarily a string
String x = (String)o; // ok compile-time, but might give a runtime exception if o is not infact a String
형식 캐스트는 효과적으로 다음과 같이 말합니다. 이것이 캐스트 클래스에 대한 참조라고 가정하고 그렇게 사용합니다.이제 o가 실제로는 Integer라고 합니다.String이 의미가 없고 예기치 않은 결과가 나온다고 가정하면 런타임 체크와 런타임 환경에 문제가 있음을 알리기 위한 예외가 필요합니다.
실제 사용에서는 보다 일반적인 클래스에서 작업하는 코드를 작성할 수 있지만, 서브클래스가 무엇인지 알고 있고, 서브클래스로 취급할 필요가 있는 경우에는 서브클래스에 코드를 캐스팅합니다.일반적인 예로는 Object.equals()를 덮어씁니다.자동차를 위한 클래스가 있다고 가정합니다.
@Override
boolean equals(Object o) {
if(!(o instanceof Car)) return false;
Car other = (Car)o;
// compare this to other and return
}
제공하신 코드가 실행 시 작동하지 않는 것을 알 수 있습니다.왜냐하면 우리는 그 표현이new A()
결코 활자의 대상이 될 수 없다B
.
하지만 컴파일러는 그렇게 보지 않습니다.컴파일러는 캐스트가 허용되는지 여부를 확인할 때 다음과 같이 표시됩니다.
variable_of_type_B = (B)expression_of_type_A;
그리고 다른 사람들이 증명했듯이, 그런 종류의 캐스팅은 완벽하게 합법적입니다.오른쪽에 있는 표현식은 유형 객체에 대해 매우 잘 평가할 수 있습니다.B
컴파일러는 다음과 같이 인식합니다.A
그리고.B
하위 유형 관계를 가지기 때문에 코드의 "표현" 뷰와 함께 캐스팅이 작동할 수 있습니다.
컴파일러는 어떤 오브젝트 타입을 정확하게 알고 있는 경우에는 특별한 경우를 고려하지 않습니다.expression_of_type_A
정말 그렇게 될 거야스태틱 타입은A
다이나믹 타입은A
또는 의 후손A
, 「」를 한다.B
.
이 경우 Java가 런타임에 실행할 수 없는 경우 다운캐스팅을 허용하는 이유는 무엇입니까?
컴파일러가 컴파일 시에 캐스트의 성공 여부를 알 수 없기 때문이라고 생각합니다.예를 들어, 캐스팅이 실패하는 것을 보는 것은 간단하지만, 명확하지 않은 경우도 있습니다.
들어 B,A를 후 「B」 「C」 「D」가 「A」 「A」 「A」 「A」 「D」라고 합니다.public A getSomeA()
는 랜덤하게 생성된 번호에 따라 B, C 또는 D의 인스턴스를 반환합니다.을 알 수를 ""로 .따라서 나중에 결과를 다음 주소로 캐스트합니다.B
출연자가 성공할지 실패할지는 알 길이 없다.따라서 컴파일러는 캐스팅이 성공한다고 가정해야 합니다.
@ 오리지널 포스터 - 인라인 댓글 참조.
public class demo
{
public static void main(String a[])
{
B b = (B) new A(); // compiles with the cast, but runtime exception - java.lang.ClassCastException
//- A subclass variable cannot hold a reference to a superclass variable. so, the above statement will not work.
//For downcast, what you need is a superclass ref containing a subclass object.
A superClassRef = new B();//just for the sake of illustration
B subClassRef = (B)superClassRef; // Valid downcast.
}
}
class A
{
public void draw()
{
System.out.println("1");
}
public void draw1()
{
System.out.println("2");
}
}
class B extends A
{
public void draw()
{
System.out.println("3");
}
public void draw2()
{
System.out.println("4");
}
}
다운캐스트는 업캐스트된 물체를 다룰 때 작동합니다.업캐스트:
int intValue = 10;
Object objValue = (Object) intvalue;
그래서 지금 이거objValue
는 항상 조정할 수 있습니다.int
는 냐하면 because because because because because because because because because because because이기 때문이다.Integer
,
int oldIntValue = (Integer) objValue;
// can be done
, '아예'가 있기 때문에objValue
입니다.이 할 수 .String
int
할 수 String
.
다운캐스팅은 제가 항상 사용하는 다음 코드 조각에서 매우 유용합니다.따라서 다운캐스팅이 유용하다는 것을 증명합니다.
private static String printAll(LinkedList c)
{
Object arr[]=c.toArray();
String list_string="";
for(int i=0;i<c.size();i++)
{
String mn=(String)arr[i];
list_string+=(mn);
}
return list_string;
}
String을 Linked List에 저장합니다.Linked List 요소를 가져오면 개체가 반환됩니다.요소를 문자열(또는 다른 클래스 개체)로 액세스하려면 다운캐스팅이 도움이 됩니다.
자바는 우리가 잘못된 일을 하고 있다고 믿고 다운캐스트 코드를 컴파일할 수 있게 해줍니다.그래도 사람이 실수를 하면 런타임에 잡힌다.
다음 예시를 검토해 주십시오.
public class ClastingDemo {
/**
* @param args
*/
public static void main(String[] args) {
AOne obj = new Bone();
((Bone) obj).method2();
}
}
class AOne {
public void method1() {
System.out.println("this is superclass");
}
}
class Bone extends AOne {
public void method2() {
System.out.println("this is subclass");
}
}
여기서는 Bone 서브클래스의 오브젝트를 생성하여 슈퍼클래스 AONE 레퍼런스에 할당했습니다.이제 슈퍼클래스 레퍼런스는 서브클래스의 메서드2에 대해 알 수 없습니다.즉, 컴파일 시간 동안 Bone의 메서드2를 알 수 없습니다.따라서 우리는 결과 참조가 하위 클래스의 방법의 존재에 대해 알 수 있도록 슈퍼 클래스의 참조를 하위 클래스 참조로 다운다운해야 한다. 즉, Bone
Java에서 다운캐스팅을 수행하고 런타임 예외를 방지하려면 다음 코드를 참조하십시오.
if (animal instanceof Dog) {
Dog dogObject = (Dog) animal;
}
개.
instanceof는 참조 변수에 특정 유형의 객체 참조가 포함되어 있는지 여부를 확인하기 위해 사용되는 키워드입니다.
개체의 다운캐스트 변환을 수행할 수 없습니다.오직.
DownCasting1 _downCasting1 = (DownCasting1)((DownCasting2)downCasting1);
긍정적이다
class DownCasting0 {
public int qwe() {
System.out.println("DownCasting0");
return -0;
}
}
class DownCasting1 extends DownCasting0 {
public int qwe1() {
System.out.println("DownCasting1");
return -1;
}
}
class DownCasting2 extends DownCasting1 {
public int qwe2() {
System.out.println("DownCasting2");
return -2;
}
}
public class DownCasting {
public static void main(String[] args) {
try {
DownCasting0 downCasting0 = new DownCasting0();
DownCasting1 downCasting1 = new DownCasting1();
DownCasting2 downCasting2 = new DownCasting2();
DownCasting0 a1 = (DownCasting0) downCasting2;
a1.qwe(); //good
System.out.println(downCasting0 instanceof DownCasting2); //false
System.out.println(downCasting1 instanceof DownCasting2); //false
System.out.println(downCasting0 instanceof DownCasting1); //false
DownCasting2 _downCasting1= (DownCasting2)downCasting1; //good
DownCasting1 __downCasting1 = (DownCasting1)_downCasting1; //good
DownCasting2 a3 = (DownCasting2) downCasting0; // java.lang.ClassCastException
if(downCasting0 instanceof DownCasting2){ //false
DownCasting2 a2 = (DownCasting2) downCasting0;
a2.qwe(); //error
}
byte b1 = 127;
short b2 =32_767;
int b3 = 2_147_483_647;
// long _b4 = 9_223_372_036_854_775_807; //int large number max 2_147_483_647
long b4 = 9_223_372_036_854_775_807L;
// float _b5 = 3.4e+038; //double default
float b5 = 3.4e+038F; //Sufficient for storing 6 to 7 decimal digits
double b6 = 1.7e+038;
double b7 = 1.7e+038D; //Sufficient for storing 15 decimal digits
long c1 = b3;
int c2 = (int)b4;
//int 4 bytes Stores whole numbers from -2_147_483_648 to 2_147_483_647
//float 4 bytes Stores fractional numbers from 3.4e−038 to 3.4e+038. Sufficient for storing 6 to 7 decimal digits
float c3 = b3; //logic error
double c4 = b4; //logic error
} catch (Throwable e) {
e.printStackTrace();
}
}
}
언급URL : https://stackoverflow.com/questions/380813/downcasting-in-java
'programing' 카테고리의 다른 글
vue2-google-maps를 사용하여 폴리라인 생성 (0) | 2022.08.28 |
---|---|
#ifdef에 'or' 조건을 추가하는 방법 (0) | 2022.08.28 |
키스토어 파일에서 인증서 이름과 별칭을 확인하는 방법 (0) | 2022.08.28 |
문자열이 Java에서 정수를 나타내는지 확인하는 가장 좋은 방법은 무엇입니까? (0) | 2022.08.28 |
JVM에서 사용하도록 프록시를 설정하려면 어떻게 해야 합니까? (0) | 2022.08.28 |