Java Arrays与Generics

Sac*_*rma 3 java generics reflection collections

假设一个SuperClass America和它的两个SubClasses SouthAmerica和NorthAmerica

情况1

对于数组:

America[] am = new SouthAmerica[10]; //why no compiler error
am[0]= new NorthAmerica();    //ArrayStoreException at RunTime
Run Code Online (Sandbox Code Playgroud)

案例2

在Genrics中:

ArrayList<America> ame = new ArrayList<SouthAmerica>(); //this does not compile
Run Code Online (Sandbox Code Playgroud)

我的问题不是为什么案例2不编译,但我的问题是为什么案例1编译.我的意思是还有什么可以做这个基础数组类型和子数组对象?

Ben*_*aum 13

那是因为数组是协变的.

数组的这种行为在很大程度上被认为是错误:

String[] strings = new String[1];
Object[] objects = strings;
objects[0] = new Integer(1); // RUN-TIME FAILURE
Run Code Online (Sandbox Code Playgroud)

通用集合 - 更新,修复了这个错误.

您可以使用有界通配符表示法<? super America>:

ArrayList<? super America> = new ArrayList<SouthAmerica>();
Run Code Online (Sandbox Code Playgroud)

这将允许您添加到列表中,但它将避免有问题的行为.

请参阅此官方教程,了解如何使用它们.

  • 这是Sun为了Arrays.sort(any_array)之类的方法而犯的错误?????? (2认同)
  • 我不会称之为错误; 数组是协变的,而泛型类不是向后兼容性的结果; 这就解释了为什么你在列表上有一个专用的`.toArray()`方法,以便在运行时需要一个"类型安全"的数组. (2认同)
  • @fge当我写错误时,我的意思是回想起来.我相信Gosling在编写Java时会考虑泛型,不会发生数组协方差.在他的位置,设计一种没有泛型的语言 - 这似乎是合理的行为.在我之前对OP的评论中,我讨论了为什么协方差在没有泛型的语言中很好.这就是为什么像C#这样的其他语言非常了解问题本质,以及它解决的问题. (2认同)
  • @BenjaminGruenbaum,.NET语言有机会学习Java的错误;)但更广泛地说,在某些时候,Java语言desingers必须打破向后兼容性; 如果不这样做,在未来某个时候推广Java将变得不可持续. (2认同)