请注意,为什么我应该在左侧(变量声明)和右侧(对象分配)提供Generic类? 从技术上讲,我可以向左或向右跳过它(参见alist2或aList2),与aList1相比,aList2和aList3的缺点是什么?
ArrayList<String> aList1 = new ArrayList<String>();
ArrayList<String> aList2 = new ArrayList();
ArrayList aList3 = new ArrayList<String>();
奖金问题,刚刚进入我的脑海并编译,但这对于aList4和aList5意味着什么?
ArrayList<String> aList4 = new ArrayList<>();
ArrayList<?> aList5 = new ArrayList<String>();
提前谢谢。
亲切的问候, 赫尔曼
答案 0 :(得分:3)
ArrayList
是原始类型。 Java Spec says以下是关于它们的:
原始类型的使用仅允许作为遗留代码兼容性的让步。在将泛型引入Java编程语言之后编写的代码中使用原始类型是非常不鼓励的。未来版本的Java编程语言可能会禁止使用原始类型。
ArrayList<?>
是一个通配符类型,特别是所有ArrayLists的超类型,不管它们的类型参数如何。由于我们不知道List中的元素类型,因此使用它可以比使用普通的ArrayList更少。例如,您无法向其中添加null
以外的任何内容,并且您从列表中获取的每个内容仅为Object
。
ArrayList<>
是ArrayList<X>
的简写表示法,其中X
替换为作业左侧的type参数。也就是说,ArrayList<String> list = new ArrayList<>()
完全等同于ArrayList<String> list = new ArrayList<String>()
。菱形运算符仅存在于Java 7及更高版本中,并且只能用于编译器足够智能以推断类型的位置,但在这些情况下,它通常是使用泛型的最正确和最简洁的方式。
答案 1 :(得分:1)
第一个列表是用于声明Java 6及更早版本的标准版本,以避免从新的arraylist中获取原始类型。从Java 7开始,您可以安全地使用第二个列表。
我不确定第三个列表在Java 7中是否安全,但我认为无论如何都会将所有内容存储为对象(原始类型问题)或者甚至可能不编译。
第四个列表基本上等同于第二个列表,第五个列表相当于第三个列表。
编辑:刚刚测试过,第三个列表确实会返回原始类型,所以我会反对它。我也错过了第二个列表在ArrayList的new
声明中缺少一个菱形运算符(你应该有)。
答案 2 :(得分:0)
您应该使用最适合您实施的Generic
类。也就是说,如果您只关心应该使用Collection
的项目集合,如果您需要保留顺序,则应使用界面List
。原因是你应该:
编程到接口而不是实现 GoF
为什么这样好?好吧,因为它使更改实现变得更加容易。假设您将来要从ArrayList更改为LinkedList。然后,只需将呼叫更改为new ArrayList
到new LinkedList
即可。对于您自己的代码也是如此,尝试始终将接口用于任何不仅仅是数据对象的类。这将使您考虑对象之间的接口而不是实现,这样您就可以始终编写一些蹩脚的内容,然后在您发现需要的时候优化实现,而不会破坏您的代码。
那么为什么不推断你的例子的类型呢? 好吧,主要是因为程序不知道列表包含哪些类型,这意味着你必须通过了解类型或通过弄清楚类型来将这些对象强制转换为类型。
至于为什么aList2不好,我只想参考这个discussion