Java类中的懒惰类? [英] Lazy class cast in Java?
问题描述
有人可以告诉我为什么我在这个片段中没有得到 ClassCastException
?我非常感兴趣,为什么它不工作,因为我的期望。我现在不在乎这是否是不好的设计。
public class Test {
static class父{
@Override
public String toString(){returnparent; }
}
static class ChildA extends父{
@Override
public String toString(){returnchild A; }
}
static class ChildB extends父{
@Override
public String toString(){returnchild B; }
}
public< C extends Parent> C get(){
return(C)new ChildA();
}
public static void main(String [] args){
Test test = new Test();
//应该抛出ClassCastException ...
System.out.println(test。< ChildB> get());
// throws ClassCastException ...
System.out.println(test。< ChildB> get()。toString());
}
}
这是java版本,编译和运行输出:
$ java -version
java版本1.7.0_17
Java环境(构建1.7.0_17-b02)
Java HotSpot(TM)64位服务器VM(构建23.7-b01,混合模式)
$ javac -Xlint:unchecked Test.java
Test .java:24:warning:[unchecked] unchecked cast
return(C)new ChildA();
^
必需:C
found:ChildA
其中C是一个类型变量:
C extends方法中声明的父< C> get $ b 1 warning
$ java Test
child A
线程main中的异常java.lang.ClassCastException:Test $ ChildA不能转换为Test $ ChildB
。 main(Test.java30)
类型擦除:泛型只是一个语法特征,通过编译器(出于兼容性原因),并在需要时替换为 。
在运行时, C get
方法不知道 C
(这就是为什么你不能实例化 new C()
)。 test。< ChildB> get()
实际上是对 test.get
的调用。 return(C)new ChildA()
转换为 return(Object)new ChildA()
无限类型 C
是父
(其最左边界)。然后,不需要转换,因为 println
期望将 Object
作为参数。
另一方面, test。< ChildB> get()。toString()
失败,因为在调用
toString()
之前,将get()强制转换为 ChildB
注意,像 myPrint(test。< ChildB> get())
的调用也将失败。 返回的
Parent
返回键入 ChildB
在调用 myPrint
时完成。
public static void myPrint child){
System.out.println(child);
}
Can someone please enlighten me as to why I don't get a ClassCastException
in this snippet? I'm strictly interested into why it isn't working as I was expecting. I don't care at this point whether this is bad design or not.
public class Test {
static class Parent {
@Override
public String toString() { return "parent"; }
}
static class ChildA extends Parent {
@Override
public String toString() { return "child A"; }
}
static class ChildB extends Parent {
@Override
public String toString() { return "child B"; }
}
public <C extends Parent> C get() {
return (C) new ChildA();
}
public static void main(String[] args) {
Test test = new Test();
// should throw ClassCastException...
System.out.println(test.<ChildB>get());
// throws ClassCastException...
System.out.println(test.<ChildB>get().toString());
}
}
This is the java version, compilation, and run output:
$ java -version
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
$ javac -Xlint:unchecked Test.java
Test.java:24: warning: [unchecked] unchecked cast
return (C) new ChildA();
^
required: C
found: ChildA
where C is a type-variable:
C extends Parent declared in method <C>get()
1 warning
$ java Test
child A
Exception in thread "main" java.lang.ClassCastException: Test$ChildA cannot be cast to Test$ChildB
at Test.main(Test.java:30)
Type erasure: generics is only a syntactic feature that is removed by the compiler (for compatibility reasons) and replaced by casts where required.
In runtime, the method C get
doesn't know the type of C
(that is why you cannot instantiate new C()
). An invocation of test.<ChildB>get()
is actually an invocation of test.get
. return (C) new ChildA()
is converted to return (Object) new ChildA()
because the erasure of the unbounded type C
is Parent
(its leftmost bound). Then, no cast is required because println
expects an Object
as argument.
On the other hand test.<ChildB>get().toString()
fails, because test.<ChildB>get()
is casted to ChildB
before invoking toString()
.
Note that an invocation like myPrint(test.<ChildB>get())
will also fail. The cast from the Parent
returned by get
to type ChildB
is done when myPrint
is invoked.
public static void myPrint(ChildB child) {
System.out.println(child);
}
这篇关于Java类中的懒惰类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!