有人可以详细解释以下类型之间的区别吗?
List List<Object> List<?>
让我更具体一点。我什么时候要使用
// 1 public void CanYouGiveMeAnAnswer(List l) { } // 2 public void CanYouGiveMeAnAnswer(List<Object> l) { } // 3 public void CanYouGiveMeAnAnswer(List<?> l) { }
正如其他文章所指出的那样,你正在询问有关称为泛型的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) 。但是,这些对象处理的数据类型与对其执行的操作正交。
add(),get(),size()
放在一起,你将经常看到以下类型的代码:
List<String> L = new ArrayList<String>();
你应该读为“ L是一种处理String对象的列表”。当你开始处理Factory类时,处理合同而不是特定的实现至关重要。工厂在运行时会产生各种类型的对象。
L
String
Factory
使用泛型非常容易(大多数时候)。
有一天,你可能决定要实现自己的通用类。也许你想编写一个新的数据库抽象接口,以消除各种数据存储之间的差异。当定义该通用类时,将<t>用作将由方法操作的对象的占位符。
<t>
如果仍然感到困惑,请对List使用通用类,直到你感到舒适为止。稍后,你可以更有信心地深入实施。或者,你可以查看JRE附带的各种List类的源代码。开源很棒。