一尘不染

Java泛型:List, List<Object>, List<?>

java

有人可以详细解释以下类型之间的区别吗?

List
List<Object>
List<?>

让我更具体一点。我什么时候要使用

// 1 
public void CanYouGiveMeAnAnswer(List l) { }

// 2
public void CanYouGiveMeAnAnswer(List<Object> l) { }

// 3
public void CanYouGiveMeAnAnswer(List<?> l) { }

阅读 996

收藏
2020-03-05

共1个答案

一尘不染

正如其他文章所指出的那样,你正在询问有关称为泛型的Java功能。在C 中,这称为模板。Java中的此功能通常比C 中的功能更易于使用。

让我从功能上回答你的问题(如果这不是面向对象的讨论的顽皮话)。

在泛型之前,有像Vector这样的具体类。

Vector V = new Vector();

向量可容纳你提供的任何对象。

V.add("This is an element");
V.add(new Integer(2));
v.add(new Hashtable());

他们通过将赋予它的所有值转换为对象(所有Java类的根)来实现此目的。当你尝试检索存储在Vector中的值时,需要将值强制转换回原始类(如果你想对其进行有意义的操作)。

String s = (String) v.get(0);
Integer i = (Integer) v.get(1);
Hashtable h = (Hashtable) v.get(2);

投放会很快变老。不仅如此,编译器还向你抱怨未经检查的强制转换。像这样进行转换的最紧迫的问题是,Vector的使用者必须在编译时知道其值的类别,才能正确进行转换。如果Vector的生产者和使用者的消费者完全相互隔离(请考虑RPC消息),这可能是一个致命的问题。

输入泛型。泛型试图创建强类型的类来进行泛型操作。

ArrayList<String> aList = new ArrayList<String>();
aList.add("One");
String element = aList.get(0); // no cast needed
System.out.println("Got one: " + element); 

《设计模式》一书鼓励读者从合同而非具体类型的角度进行思考。将变量与实现类分开是明智的(和代码重用)。

考虑到这一点,你可能会认为,所有实现List对象应该做同样的一套东西:add(),get(),size()等有了一点点反思,你可以想像列表操作的许多实现服从以各种方式列表合同(例如ArrayList) 。但是,这些对象处理的数据类型与对其执行的操作正交。

放在一起,你将经常看到以下类型的代码:

List<String> L = new ArrayList<String>();

你应该读为“ L是一种处理String对象的列表”。当你开始处理Factory类时,处理合同而不是特定的实现至关重要。工厂在运行时会产生各种类型的对象。

使用泛型非常容易(大多数时候)。

有一天,你可能决定要实现自己的通用类。也许你想编写一个新的数据库抽象接口,以消除各种数据存储之间的差异。当定义该通用类时,将<t>用作将由方法操作的对象的占位符。

如果仍然感到困惑,请对List使用通用类,直到你感到舒适为止。稍后,你可以更有信心地深入实施。或者,你可以查看JRE附带的各种List类的源代码。开源很棒。

2020-03-05