Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么要从列表中选演员<;A>;列出<;B>;不推荐?_Java_List_Casting - Fatal编程技术网

Java 为什么要从列表中选演员<;A>;列出<;B>;不推荐?

Java 为什么要从列表中选演员<;A>;列出<;B>;不推荐?,java,list,casting,Java,List,Casting,我希望如果我有两门课: public class A {} public class B extends A {} 我可以从列表中判断这是不推荐的。那是真的吗 如果我知道它会给我一个列表,为什么做这个演员是一个如此糟糕的做法 请注意,我想知道为什么在这种情况下,这是一种不好的做法,而不是为什么会有警告。“这是一个不好的做法,因为它会产生一个警告”并不是一个好的答案。一个苹果是一个水果,但是一个苹果列表不是一个水果列表 如果是的话,你可以在苹果列表中放一根香蕉。为了让这有意义,你必须理解list

我希望如果我有两门课:

public class A {}
public class B extends A {}
我可以从
列表中判断这是不推荐的。那是真的吗

如果我知道它会给我一个
列表
,为什么做这个演员是一个如此糟糕的做法


请注意,我想知道为什么在这种情况下,这是一种不好的做法,而不是为什么会有警告。“这是一个不好的做法,因为它会产生一个警告”并不是一个好的答案。

一个苹果是一个水果,但是一个苹果列表不是一个水果列表


如果是的话,你可以在苹果列表中放一根香蕉。为了让这有意义,你必须理解
list
list
是两种不同的类型,没有层次关系,即使
a
B
是层次关系。即使
B
a
的子类,将
列表
强制转换为
列表
也是不好的,因为它可以允许您将
a
(而不是
B
)的实例添加到该列表中,并且编译器会很乐意这样做,即使它不符合集合的实际(运行时)类型


我不知道在Java中可以绕过这一点,但如果可以的话,那只是因为类型擦除:因为Java创建了一个类,比如
List
,对于该泛型类的不同“实现”,它只在编译代码之前在代码中添加强制转换。这与(比如)C#相反,C#实际上只将
列表作为“编译”模板(称为“泛型定义”)使用,以根据需要创建具体类型。

泛型的工作方式略有不同,因此list不是list类型,尽管BA类型,但直接转换列表是不好的,因为它颠覆了Java类型系统。强制转换总是会成功,但稍后当您检索项目时,程序可能会出现
ClassCastException
而失败,此时错误的来源可能不清楚

通常,您希望您的程序在尽可能接近错误源的地方失败。如果您强制转换列表,在有人实际尝试访问元素之前,它可能会被传递一段时间,当它抛出
ClassCastException
时,可能很难将其追溯到该强制转换(至少比程序在强制转换时失败要难)

从您的评论来看,您似乎确信
listA
中的所有内容实际上都是
B
,在这种情况下,我建议:

List<B> listB = new ArrayList(listA.size());
for (A a : listA) {
  if (a == null || a instanceof B) {
    listB.add((B) a);
  } else {
    //Either ignore or throw exception
  }
}
List listB=newarraylist(listA.size());
对于(A:listA){
if(a==null | | a实例B){
清单B.添加((B)a);
}否则{
//忽略或抛出异常
}
}

我把水果列表和苹果列表放在一起,因为我知道那里只有苹果。为什么这是一种不好的做法?@Roberto那么为什么不从苹果列表开始呢?无法控制返回给我水果列表的来源;我想用方法创建一个Apple类来简化对这些结果的处理。如果class
B
有class
A
没有的方法呢?通过listB,您应该能够安全地调用类似于
listB.get(0).methodFromB()
,但由于
listB
最初是
listA
,因此在对象B旁边,它可能还包含无法调用
methodFromB()
的对象A。如果我正在强制转换,那是因为我知道那里没有任何A。。。我的意思是:
objecta=“string”;整数b=(整数)a编译器不会对此抱怨…好吧,但这是你的知识(假设)。编译器无法知道,这就是为什么它会给您警告。由于以后没有人能阻止您将对象放入
listA
中,因此对listB来说可能很危险。这就是为什么不建议从
List
转换为
List
List<B> listB = new ArrayList(listA.size());
for (A a : listA) {
  if (a == null || a instanceof B) {
    listB.add((B) a);
  } else {
    //Either ignore or throw exception
  }
}