多态性中的错误



我对java有点陌生,我有一个关于多态性和可能的错误的问题。假设我们有:

public interface Animal {
}
public abstract class Cat implements Animal{
}
public abstract class Fish implements Animal {
}
public class Salmon extends Fish{
}
public class Tiger extends Cat{
}

和假设我们有这样的东西:

Animal t1 = new Tiger();
Fish f1 = new Salmon();
Tiger t2= new Tiger();
Salmon s1 = new Salmon();

以下几行错误是什么(编译时错误,运行时错误或无错误):

Cat c1 = new Cat();
Cat c2 = (Tiger) t1;
Animal a1 = s1;
Animal a2 = new Animal();
Fish f1 = (Fish) t2;
Animal a3 = (Fish) s1;
Animal a4 = (Cat) new Tiger();
Cat c3 = (Cat) new Salmon();

我已经像咆哮一样回答了它,但我认为它有点奇怪,我没有发现运行时错误。如果他们都是正确的,你可以做一个例子,我们有运行时错误(在这个多态性的概念)

我的回答:

a  compile error
b  no error
c  no error
d  compile error
e  compile error
f  no error
g  no error
h  compile error

专注于"如何在运行时获得异常"的部分。

你认为Cat c3 = (Cat) new Salmon();是错误的。显然,编译器已经告诉你了。

为什么?因为编译器可以"看到"你创建了一个Salmon,然后你想把它当作Cat,这是没有意义的。

你唯一需要做的就是"过去"编译器要"隐藏";这个事实,比如:

Salmon s1 = new Salmon();
Animal a3 = (Fish) s1;
Cat c3 = (Cat) a3;

一旦你引入a3,你就可以"隐藏"。事实上,s1实际上是一个鲑鱼。

当然即使在我的例子中,一个更聪明的编译器也能理解a3一定是一只鲑鱼,而不是一只猫。但是java把它玩得"简单而保守"。在这里。编译器只识别最基本的类型转换违规,无论好坏,java语言忽略了在编译时也可以检测到的许多情况。这使得实现编译器更容易,但代价是您的代码在运行时更容易暴露于此类异常。

由于Java只支持类的单继承,因此它可以验证类之间的强制转换是否可能有效,因为在强制转换时,其中一个类必须是另一个类的祖先。您可以向上转换,例如TigerCat,也可以向下转换,例如CatTiger

我忽略了愚蠢的身份转换,例如TigerTiger,但它当然也是允许的。

不能将一个类强制转换为另一个不"相关"的类。

。对于接口,编译器不能验证,因为允许多重继承,这意味着在编译时,总是可以将类或接口强制转换为接口,也总是可以将接口强制转换为类或另一个接口。只能在运行时验证强制转换。

由于没有两个类从同一个基类继承,因此不能为类之间的强制转换设置运行时错误。编译器总是会捕获这个错误。

由于您只有一个接口,并且所有的类都实现了该接口,因此您不能设置将转换为接口的运行时错误。

这意味着要设置一个运行时错误,你需要将一个接口转换为一个真实对象不兼容的类,例如从Animal t1(真实对象Tiger)转换为SalmonFish

Salmon s2 = (Salmon) t1; // ClassCastException: class Tiger cannot be cast to class Salmon

你的答案都是正确的。较新的编译器应该能够找到在您的示例中强制转换失败的情况。运行时异常只会在编译器将失去实际类型跟踪的情况下抛出,因为类型是向下转换的:

public Cat catterize(Animal a) {
return (Cat) a; // this line should yield an unsafe typecast warning!
}
...
Salmon salmon = new Salmon();
Cat cat = catterize(salmon); // This is compiletime legal, but will ultimately throw a ClassCastException.

相关内容

  • 没有找到相关文章

最新更新