Java 泛型:列表、列表<对象>、列表<?>

新手上路,请多包涵

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

 List
List<Object>
List<?>

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

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

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

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

原文由 ForYourOwnGood 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 313
1 个回答

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

让我从功能上回答您的问题(如果这不是 OO 讨论的顽皮词)。

在泛型之前,有像 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() ,with little a- etc.反射,您可以想象许多以各种方式遵守 List 契约的 List 操作的实现(例如 ArrayList )。然而,这些对象处理的数据类型与对它们执行的操作是正交的。

将它们放在一起,您会经常看到以下类型的代码:

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

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

使用泛型非常容易(大部分时间)。

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

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

查看 有关泛型的 Oracle/Sun 文档。干杯。

原文由 jjohn 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题