这是我的代码: -
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);
我创建了一个ArrayList
动物(超类)作为myanimals
并存储了一个狗(子类)作为第一个元素。然后myanimals.get(0)
返回一个狗类型对象。当此类型对象在语句dog newdog = myanimals.get(0)
中由狗类型引用引用时,它会显示错误说明:
类型不匹配,无法从动物转换为狗。
为什么会这样?
答案 0 :(得分:4)
方法调用myanimals.get(0)
返回类型为Animal
的对象引用。尝试{strong> Typecasating Animal
作为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;
这会抛出编译时错误。同样是你的案子的问题。据说ArrayList
包含animal
。因此,即使您向其添加animal
,它也会返回dog
。
答案 1 :(得分:2)
Java是一种静态类型语言。即Java编译器根据源代码检查代码是否存在类型不匹配。您的源代码说,myanimals.get(0)
属于Animal类型。
继承是一种“IS-A”关系,即Dog IS-A Animal,可以用作Animal类型变量的值。但事实恰恰相反:动物不是IS-A狗,它可能是(这使得铸造成为可能 - 后来更多)。这就是你输入类型不匹配的原因。
只有在运行时,在将源代码编译成字节码(并删除泛型类型)很久之后,myanimals.get(0).getClass()
看起来似乎是巧合。编译器之前无法知道。
这是有道理的:它可以防止静态分析可能捕获的运行时错误。
但是,你是开发人员,他肯定知道,myanimals.get(0).getClass()
在运行时会是Dog类型,所以你可以像在Shashwat的回答中那样承担责任并应用强制转换。编译器仍会检查是否可以进行此类转换,如果是,则会相信您的话。
答案 2 :(得分:0)
基本上,ArrayList的类型是<!DOCTYPE html>
<html>
<head>
<title>Tip</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
<%= yield %>
</body>
</html>
,你可以添加任何种类的动物,不仅仅是狗,还有猫,老鼠和鹦鹉。虽然您的案例中的基础类型确实是animal
,但您无法安全地了解这一点。否则,您将遇到运行时异常,如下所示:
dog