2013-11-21 69 views
3

请,我为什么要提供通用类左侧(变量声明)和右侧(对象分配)? 我可以在技术上向左或向右跳过它(请参阅alist2或aList2),aList2和aList3与aList1相比有什么缺点?Java泛型使用

ArrayList<String> aList1 = new ArrayList<String>(); 
ArrayList<String> aList2 = new ArrayList(); 
ArrayList   aList3 = new ArrayList<String>(); 

奖金问题,刚进入我的脑海,它编译,但这意味着什么对于ListList和aList5?

ArrayList<String> aList4 = new ArrayList<>(); 
ArrayList<?>  aList5 = new ArrayList<String>(); 

在此先感谢您。

亲切的问候, 赫尔曼

+0

绝不是一个完整的答案,但aList3不会为你设计一个类的泛型是非常有益的。假设你有一个'ArrayList '用一个List3,你必须将任何项目从它中投射到一个Car中。反之亦然,在没有泛型的情况下,你将事物添加为技术上有效的对象,但是你不希望将一个'Car'类型的对象添加到一个ArrayList,用于存储'Person'类型的对象。 – Compass

回答

1

第一清单,用于声明Java 6的标准及更早版本,以避免新的ArrayList抢夺原料类型。从Java 7开始,您可以安全地使用第二个列表。

我不确定如果第三列表是在Java 7中的安全,但我相信它会无论是存储的一切,无论如何对象(原始类型的问题),或者甚至可能没有编译。

第四列表是本质上等价于所述第二列表中,和第五列表相当于第三列表。

编辑:刚才测试,第三列表不会返回原始类型,所以我会建议反对。我也错过了第二个列表缺少ArrayList的new声明中的钻石操作符(您应该有)。

+1

*从Java 7开始,您可以安全地使用第二个列表*,您的意思是'aList4',而不是'aList2'。 –

+0

啊,是的,我错过了那里的钻石操作员的缺乏,一会儿。 – Rogue

+0

请注意,第二个列表'aList2'编译自Java 5以来的警告。 –

3

ArrayList是原始类型。 Java Spec says关于它们如下:

原始类型的使用仅允许作为遗留代码兼容性的让步。强烈建议在将泛型引入Java编程语言之后编写的代码中使用原始类型。未来版本的Java编程语言可能会禁止使用原始类型。

ArrayList<?>是通配符类型,特别是所有ArrayList的超类型,无论它们的类型参数如何。由于我们不知道列表中元素的类型,因此您可以少用普通的ArrayList。例如,您不能添加除null以外的任何内容,并且您从列表中获取的每个内容仅为Object

ArrayList<>ArrayList<X>的简写符号,其中X被替换为赋值左侧的类型参数。也就是说,ArrayList<String> list = new ArrayList<>()完全等同于ArrayList<String> list = new ArrayList<String>()。菱形运算符只存在于Java 7及更高版本中,并且只能在编译器足够聪明以推断类型的地方使用,但在这些情况下,它通常是使用泛型的最正确和最简洁的方式。

0

您应该使用Generic类,是最适合您的实现。也就是说,如果您只关心收集的物品应该使用Collection,如果您需要保留订单,则应使用接口List。这样做的原因是,你应该:

计划到接口而不是实现 GoF

这是为什么好?那么因为它使得更改实现变得更容易。假设你希望将来从ArrayList改变为LinkedList。然后这只是将呼叫更改为new ArrayListnew LinkedList。对于你自己的代码也是一样,试着总是使用一个接口来接收任何不仅仅是一个数据对象的类。这会让你思考你的对象之间的接口而不是实现,这样你就可以总是编写一些糟糕的代码,然后在你不需要破坏代码的情况下发现你需要的时候再细化你的实现。

article for more info

那么,为什么不好不能推断类型的例子吗? 主要是因为程序不会知道列表包含的是什么类型,这意味着要么通过知道类型或通过计算类型来将这些对象转换为它们的类型。

至于为什么aList2不好我就参考这个discussion