java接口引用向下转换
尽管这些接口不相关,但上面的代码似乎是编译的,如果我将这些接口更改为类,它显然不会编译。为什么接口的行为是这样的我想Eliot想说的是,如果初始分配不同,这些强制转换可能会成功java接口引用向下转换,java,interface,Java,Interface,尽管这些接口不相关,但上面的代码似乎是编译的,如果我将这些接口更改为类,它显然不会编译。为什么接口的行为是这样的我想Eliot想说的是,如果初始分配不同,这些强制转换可能会成功 interface A {} interface B{} interface C{} A a = new A(){}; B b = (B)a; C c = (C)b; Java不支持多重继承,这就是它不能处理类的原因。但是,由于接口可以被多次实现,语法可能还可以。我
interface A {}
interface B{}
interface C{}
A a = new A(){};
B b = (B)a;
C c = (C)b;
Java不支持多重继承,这就是它不能处理类的原因。但是,由于接口可以被多次实现,语法可能还可以。我想Eliot想说的是,如果初始赋值不同,这些强制转换可能会成功
interface A {}
interface B{}
interface C{}
A a = new A(){};
B b = (B)a;
C c = (C)b;
Java不支持多重继承,这就是它不能处理类的原因。但是,由于接口可以多次实现,因此语法可能还可以。在我的评论中,如果接口兼容,那么代码在运行时可能会成功。但是,如果接口不兼容,那么您可能会遇到灾难性的运行时错误。比如说,
class MyClass implements A, B, C {}
interface A {}
interface B{}
interface C{}
A a = new MyClass();
B b = (B)a;
C c = (C)b;
如果随后提供实现1
在编译时,编译器相信您知道自己在做什么。并允许您将a
转换为B
(然后分配给B
)。但是,在运行时会得到java.lang.ClassCastException
,因为接口不兼容
1
a
只是另一个java.lang.Object
实例,它碰巧实现了接口a
,根据我的评论,如果接口兼容,那么您的代码在运行时可能会成功。但是,如果接口不兼容,那么您可能会遇到灾难性的运行时错误。比如说,
class MyClass implements A, B, C {}
interface A {}
interface B{}
interface C{}
A a = new MyClass();
B b = (B)a;
C c = (C)b;
如果随后提供实现1
在编译时,编译器相信您知道自己在做什么。并允许您将a
转换为B
(然后分配给B
)。但是,在运行时会得到java.lang.ClassCastException
,因为接口不兼容
1
a
只是另一个java.lang.Object
实例,它碰巧实现了接口a
接口是不相关的,但是可能有实现所有三个接口的类,所以可能有可以愉快地转换的实例
它不适用于类的原因是给定的类只能扩展一个超类,因此不能有任何类同时扩展类a
和类B
关于这一点的另一个说法是final
类。例如,您不能将String
强制转换为Map
,因为String
的子类不能实现Map
。但是您可以将Date
或ArrayList
强制转换为Map
,因为可能存在适合的子类
请注意,此推理仅适用于编译时。无效的强制转换仍将在运行时失败。编译时类型检查应该尽可能多地捕获无效的强制转换,但并不是所有情况都可以通过静态类型检查检测到(至少在Java中不是这样)。因此,除非编译器能够保证您的强制转换没有意义,否则它将允许您这样做。接口是不相关的,但可能有实现所有三个接口的类,因此可能有可以愉快地强制转换的实例 它不适用于类的原因是给定的类只能扩展一个超类,因此不能有任何类同时扩展
类a
和类B
关于这一点的另一个说法是final
类。例如,您不能将String
强制转换为Map
,因为String
的子类不能实现Map
。但是您可以将Date
或ArrayList
强制转换为Map
,因为可能存在适合的子类
请注意,此推理仅适用于编译时。无效的强制转换仍将在运行时失败。编译时类型检查应该尽可能多地捕获无效的强制转换,但并不是所有情况都可以通过静态类型检查检测到(至少在Java中不是这样)。因此,除非编译器能够保证您的强制转换没有意义,否则它将允许它。尝试使
A
或B
(和C
)不兼容(而不是简单的标记接口)。在Java中,一切(不是原语值)都继承自Java.lang.Object
我做了以下更改。接口A{void test();}接口B{void fun();}接口C{void hi();}仍然存在相同的问题。此外,从java.lang.Object扩展的所有内容都不是一个合理的解释,因为如果我将这些接口更改为类,它确实会给出预期的编译错误“不兼容”,即在所有三个接口中都有一个test()
方法,但具有不同的(且不兼容)属性返回类型。@Thilo-我确实使返回类型与所有三个具有测试方法的接口不兼容。但代码仍然可以编译。所以不兼容似乎不是这里的解释。如果我错了,请纠正我。然而,您在下面给出的多重继承推理开始有意义了,“它不编译是因为明显的原因”,这对编译器来说并不明显。编译器只看到您将A
转换为B
或A
转换为C
。它不知道a
或b
中的实际内容。(如果a
是一个方法的参数会怎样?)“为什么接口会这样做”接口的行为方式实际上是规范。类的行为方式是这样的,因为编译器有更多的信息,可以查看层次结构。有时,编译器可以判断特定的强制转换永远不会成功,但这是规则的例外。大多数情况下,编译器不知道