类型不匹配与 ArrayLists 中的多态性

Posted

技术标签:

【中文标题】类型不匹配与 ArrayLists 中的多态性【英文标题】:Type Mismatch with polymorphism in ArrayLists 【发布时间】:2017-08-09 08:45:04 【问题描述】:

这是我的代码:-

ArrayList<animal> myanimals = new ArrayList<animal>();
dog adog = new dog();
myanimals.add(adog);
System.out.println("" + myanimals.get(0).getClass());
dog newdog = myanimals.get(0);

我创建了一个 animals(superclass)ArrayList 作为myanimals 并存储了一个 dog(subclass) 作为第一个元素。然后myanimals.get(0) 返回一个狗类型的对象。当这个狗类型对象在语句dog newdog = myanimals.get(0) 中被狗类型引用引用时,它会显示错误消息:

类型不匹配,无法从动物转换为狗。

为什么会这样?

【问题讨论】:

欢迎来到 ***。请将代码和错误发布为文本,而不是图片 感谢您的编辑建议。 @Shashwat 【参考方案1】:

方法调用myanimals.get(0) 返回Animal 类型的对象引用。尝试 TypecasatingAnimal 作为 dog 像:-

dog newdog = (dog)myanimals.get(0);

编辑 1:您询问了以下行的输出

System.out.println(myanimals.get(0).getClass());

这实际上打印出dog。为什么 ?让我们来看看。

你认为下面的程序应该输出什么:

animal a = new dog();
System.out.println(a.getClass());

这会按预期打印出dog。但这并不意味着我们可以这样做:-

animal a = new dog();
dog d = a;

这会引发 Compile-Time 错误。同样是你的情况的问题。据说ArrayList 包含animal。因此,即使您向其添加了dog,它也会返回animal

【讨论】:

但是命令:System.out.println("" + myanimals.get(0).getClass()); 将输出显示为"类多态。狗”。这不是意味着 myanimals.get(0) 返回一个狗对象吗? 虽然正确,但这并不能回答 OP 关于“为什么”不允许这样做的问题 @AayushTaneja 现在看看我的答案。我希望这次编辑可以解决问题。【参考方案2】:

基本上,ArrayList 的类型是animal,您可以在其中添加任何种类的动物,不仅是狗,还包括猫、老鼠和鹦鹉。虽然在您的情况下基础类型确实是 dog,但您不能安全地知道这一点。否则,您会遇到这种情况下的运行时异常:

ArrayList<Animal> myanimals = new ArrayList<Animal>();
Cat myCat = new Cat();
myanimals.add(myCat);
System.out.println("" + myanimals.get(0).getClass());
Dog newdog = myanimals.get(0); // <-- this would be runtime exception if Java compiler allowed this

【讨论】:

【参考方案3】:

Java 是一种静态类型语言。 IE。 Java 编译器根据源代码检查代码是否存在类型不匹配。你的源代码说,myanimals.get(0) 是动物类型。

继承是一种“IS-A”关系,即 Dog IS-A Animal,可用作 Animal 类型变量的值。但相反的情况并非如此:Animal 不是 IS-A Dog,它只是可能(这使得铸造成为可能 - 稍后会详细介绍)。这就是你得到类型不匹配的原因。

只是在运行时,在你的源代码被编译成字节码(并且泛型类型被删除)很久之后,myanimals.get(0).getClass() 似乎是巧合的 Dog。编译器以前无法知道这一点。

这是有道理的:它可以防止静态分析可能捕获的运行时错误。

但你,开发者,肯定知道myanimals.get(0).getClass() 在运行时将是 Dog 类型,所以你可以像 Shashwat 的回答那样承担责任并应用强制转换。编译器仍然会检查这种转换是否可能,如果是的话 - 它会相信你的话。

【讨论】:

非常感谢您的帮助。 @iTollu

以上是关于类型不匹配与 ArrayLists 中的多态性的主要内容,如果未能解决你的问题,请参考以下文章

Python 多态与封装

java学习之路--继承(多态的动态绑定)

将重载函数与其多态参数匹配

编译期多态和Sfinae

C++中的动态类型与动态绑定虚函数运行时多态的实现

多态与转型