Java 为什么要列出<;超类>;对象是否可以强制转换为子类对象?
我发现,案例1和案例3可以无错误地编译,但是案例2。(子类B扩展了超类,它是抽象类) 我想知道的是,为什么案例1和案例3没有编译错误。 如果是JDK错误,为什么案例2不能通过强制转换检查Java 为什么要列出<;超类>;对象是否可以强制转换为子类对象?,java,compiler-errors,Java,Compiler Errors,我发现,案例1和案例3可以无错误地编译,但是案例2。(子类B扩展了超类,它是抽象类) 我想知道的是,为什么案例1和案例3没有编译错误。 如果是JDK错误,为什么案例2不能通过强制转换检查 // case 1 List<SuperClassA> a = new ArrayList<>(); SubClassB b = (SubClassB) a; // case 2 List<Number> m = new ArrayList<>
// case 1
List<SuperClassA> a = new ArrayList<>();
SubClassB b = (SubClassB) a;
// case 2
List<Number> m = new ArrayList<>();
Long n = (Long) m; //Error:(xx,yy) java: incompatible types: java.util.List<java.lang.Number> cannot be converted to java.lang.Long
// case 3
List<Exception> e = new ArrayList<>();
RuntimeException d = (RuntimeException) e;
//案例1
列表a=新的ArrayList();
子类b=(子类b)a;
//案例2
列表m=新的ArrayList();
长n=(长)m//错误:(xx,yy)java:不兼容的类型:java.util.List无法转换为java.lang.Long
//案例3
列表e=新的ArrayList();
RuntimeException d=(RuntimeException)e;
在不安全强制转换的情况下,您会收到一条警告,因为编译器无法确定是否应该允许此强制转换。(在较旧的Java版本中,现在很难删除它,因此在没有警告的情况下允许它)
注意:Long
是一个最终的
类,它假设没有一个Long
的子类可以进行此转换
您可以创建一个类,如
class MyException extends RuntimeException implements List<Exception> {
类MyException扩展RuntimeException实现列表{
这些是有效的代码行
List<Exception> e = new MyException();
RuntimeException d = (RuntimeException) e; // ok.
List e=new MyException();
RuntimeException d=(RuntimeException)e;//确定。
请注意,案例1和案例3在运行时都会失败
在编译时,编译器只有在语言规范这么说的情况下才会抱怨不兼容的强制转换。语言规范允许情况1和3,因为它们不会100%失败 就编译器而言,案例1不会100%失败,因为它认为
a
可以包含实现List
的任何类型的实例。如果有子类b
的子类实际实现List
,如果a
实际包含该子类的实例,该怎么办如果子类b
?那么演员阵容就会成功
情况2也是如此。如果有一个子类RuntimeException
实际实现了List
,如果e
实际包含RuntimeException
子类的一个实例,那么强制转换就会成功
案例2显示了一个错误,因为Long
是final
。不可能有实现List
的子类,因此它肯定会失败
这在规范的第1部分中有规定(斜体为相关位):
给定编译时引用类型S(源)和编译时引用类型T(目标),如果由于以下规则没有发生编译时错误,则存在从S到T的转换
如果S是接口类型:
- 如果T是数组类型,那么S必须是
或java.io.Serializable
(实现的唯一接口 或发生编译时错误Cloneable
- 如果T是非
(§8.1.1)的类或接口类型,则如果存在T的超类型X和S的超类型Y,则 X和Y都是可证明不同的参数化类型,并且 如果X和Y的擦除相同,则会发生编译时错误final
- 如果T是最终类类型,则: –如果S不是参数化类型或原始类型,则T必须实现S,否则会发生编译时错误
酷,谢谢你的帮助。(我已经更正了我的疑问词,这是编译错误而非例外)“编译器只有在100%确定转换会失败时才会抱怨不兼容的转换。”不完全是:
(Integer)(String)null
不会编译,但也不会失败(如(Integer)(Object)(String)所示)空
)。