我有以下类和接口:
public interface if1 {}
public class ifTest implements if1 {}
public class HelloWorld {
public static void main(String[] args) {
//why does the following cast not work (Compiler error)
ifTest var3 = (if1) new ifTest();
}
}
为什么这个演员不起作用?我得到以下编译错误:"类型不匹配:无法从if1转换为ifTest"
答案 0 :(得分:2)
继承表示is-a
关系。 IfTest
的任何对象都是-an If1
。但是,If1
类型的引用不一定引用IfTest
类型的对象。
在教科书方案中,任何Dog
都是Animal
,但任何Animal
都不是Dog
(可能是斑马,大象,鹿等)。
投射采用以下形式:
A a = (B) c;
涉及两个步骤:
c
被投射到B
类型。B
的实例分配给变量a
(其中A
是必须等于B
的类型或{{1}的超类使编译器感到高兴,并且在运行时不会发生B
。继续使用动物隐喻,您在步骤1中将ClassCastExceptions
强制转换为Dog
,然后尝试将Animal
的该实例分配给Animal
类型的变量},编译器知道不允许这样做。
以下方法可行,因为它会将Dog
转换为IfTest
,然后将If1
分配给If1
。
IfTest
编辑正如Lew在下面的评论中指出的那样,这就是所谓的拓展演员(因为它从特定类型转变为更通用的类型,"更广泛&#34 ; type。在这个实例中,不需要强制转换,因为编译器知道根据定义对if1 var3 = (if1) new ifTest();
类型的对象的所有引用也是IfTest
。
更实际的例子是,如果你有一个对接口的引用,并希望将它转换为If1
。在这种情况下,它是"缩小"因为您从通用类型转向更具体的类型,而且#34;更窄"类型。
IfTest
请注意使用if1 var1 = (if1) new ifTest();
if (var1 instanceOf ifTest) {
ifTest var2 = (ifTest) var1;
}
来确保instanceof
实际上是var1
的实例。虽然我们知道它是,但在实际应用中IfTest
可能有多个子类型,所以这并不总是正确的。该检查可防止强制转换投掷运行时If1
。
TLDR :重要的是要知道括号内的内容必须是编译器知道可以分配给被赋值变量的类型。
答案 1 :(得分:0)
在这里,您尝试实例化一个接口。接口就像模板或类似于契约的东西 - 实现接口的类必须遵守合同并提供方法的实现。