首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java泛型: List、List<Object>、List<?>

Java泛型: List、List<Object>、List<?>
EN

Stack Overflow用户
提问于 2009-01-29 08:56:34
回答 13查看 45.9K关注 0票数 71

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

代码语言:javascript
复制
List
List<Object>
List<?>

让我说得更具体一些。我什么时候想要使用

代码语言:javascript
复制
// 1 
public void CanYouGiveMeAnAnswer(List l) { }

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

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

回答 13

Stack Overflow用户

发布于 2009-01-29 01:52:32

正如其他帖子所指出的,您正在询问一个称为泛型的Java特性。在C++中,这称为模板。Java中的这个特性通常比C++中的更容易使用。

让我从功能上回答你的问题(如果这对于OO讨论来说不是一个淘气的词)。

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

代码语言:javascript
复制
Vector V = new Vector();

向量保存您给它们的任何对象。

代码语言:javascript
复制
V.add("This is an element");
V.add(new Integer(2));
v.add(new Hashtable());

它们通过将赋予它的所有值转换为一个对象(所有Java类的根)来实现这一点。当您尝试检索存储在Vector中的值时,需要将该值转换回原始类(如果您想对其执行任何有意义的操作)。

代码语言:javascript
复制
String s = (String) v.get(0);
Integer i = (Integer) v.get(1);
Hashtable h = (Hashtable) v.get(2);

选角很快就过时了。更重要的是,编译器会向您抱怨未经检查的强制转换。像这样的强制转换最紧迫的问题是,Vector的使用者必须在编译时知道它的值的类,以便正确地强制转换。如果Vector的生产者和消费者彼此完全隔离(想想RPC消息),这可能是一个致命的问题。

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

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

设计模式一书鼓励读者从契约的角度来思考,而不是具体的类型。将变量从它们的实现类中分离出来是明智的(和代码重用)。

考虑到这一点,您可能会认为所有实现列表对象都应该做相同的事情:add()get()size()等。通过一点反思,您可以想象许多以各种方式(例如ArrayList)遵守列表契约的列表操作的实现。但是,这些对象处理的数据类型与对它们执行的操作是正交的。

把所有这些放在一起,你会经常看到以下类型的代码:

代码语言:javascript
复制
List<String> L = new ArrayList<String>();

你应该把它理解为"L是一种处理字符串对象的列表“。当您开始处理工厂类时,处理契约而不是具体的实现是至关重要的。工厂在运行时产生各种类型的对象。

使用泛型非常简单(大多数时候)。

有一天,你可能决定实现你自己的泛型类。也许你想写一个新的数据库抽象接口来消除不同数据存储之间的差异。在定义该泛型类时,您将使用<t>作为将由方法操作的对象类型的占位符。

如果您仍然感到困惑,请使用泛型类for List,直到您感到满意为止。稍后,您可以更有信心地深入研究实现。或者,您可以查看JRE附带的各种列表类的源代码。开源在这方面是很棒的。

看看Oracle/Sun docs about generics。干杯。

票数 104
EN

Stack Overflow用户

发布于 2009-01-29 01:31:00

用我自己简单的话说:

列表

将声明一个普通的集合,可以保存任何类型,并且将始终返回Object。

列表

将创建一个列表,该列表可以容纳任何类型的对象,但只能分配到另一个列表

例如,这不起作用;

代码语言:javascript
复制
List<Object> l = new ArrayList<String>();

当然,你可以添加任何东西,但只能拉取对象。

代码语言:javascript
复制
List<Object> l = new ArrayList<Object>();

l.add( new Employee() );
l.add( new String() );

Object o = l.get( 0 );
Object o2 = l.get( 1 );

最后

List

将允许您分配任何类型,包括

代码语言:javascript
复制
List <?> l = new ArrayList(); 
List <?> l2 = new ArrayList<String>();

这将被称为未知的集合,由于未知的共同点是对象,因此您将能够获取对象(巧合)

当与子类化一起使用时,unknown的重要性就来了:

代码语言:javascript
复制
List<? extends Collection> l = new ArrayList<TreeSet>(); // compiles

List<? extends Collection> l = new ArrayList<String>(); // doesn't,
// because String is not part of *Collection* inheritance tree. 

我希望使用Collection作为类型不会造成混淆,这是我脑海中唯一想到的树。

这里的不同之处在于,l是属于collection hierarchy的unknow的集合。

票数 41
EN

Stack Overflow用户

发布于 2009-01-29 01:02:09

我向您推荐Sun Microsystems提供的优秀的Java Generics tutorial"advanced" Generics tutorial。另一个很棒的资源是Java Generics and Collections书。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/490091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档