无界通配符类型List 和原始类型List之间有什么区别?

你能帮我理解无界通配符类型列表原始类型列表之间的区别吗?

List b; // unbounded wildcard type List a; // raw type 

除此之外,任何人都可以帮助我理解什么是有界类型参数列表

 List c; 

以下是三者的总结:

  • List :没有类型参数的列表。 它是一个列表,其元素是任何类型 – 元素可以是不同类型

  • List :具有无界类型参数的列表。 它的元素是一种特定但未知的类型; 元素必须都是相同的类型

  • List :一个名为T的类型参数的列表。 T提供的类型必须是扩展E的类型,或者它不是参数的有效类型。

你应该看看Effective Java,第23项:不要在新代码中使用原始类型。

要使用该书中的示例,请考虑以下示例…如果您有一个不关心其中包含哪些类型元素的集合,该怎么办? 例如,您想要查看两个集合之间共有多少个元素。 您可能会想出以下内容:

 public static int numElementsInCommon(Set s1, Set s2) { int result = 0; for (Object o : s1) { if (s2.contains(o)) { ++result; } } return result; } 

这个例子虽然有效,但由于使用了原始类型,因此不是一个好主意。 原始类型根本不是类型安全的……你最终可能会以一种非类型安全的方式修改集合并破坏你的程序。 相反,谨慎一点并使用类型安全的替代方案:

 public static int numElementsInCommon(Set s1, Set s2) { int result = 0; for (Object o : s1) { if (s2.contains(o)) { ++result; } } return result; } 

区别在于您只能向Set添加null ,并且您不能假设您从Set取出的元素。 如果您使用原始Set ,则可以添加任何您想要的内容。 numElementsInCommon方法是一个很好的示例,您甚至不需要添加任何内容,也不需要假设集合中的内容。 这就是为什么它是一个很好的候选人使用? 通配符。

希望这可以帮助。 阅读有效Java中的整个项目,它将变得清晰。

要回答你问题的第二部分……记得我说你?时候使用? 通配符,你不能假设你从集合中取出的元素? 如果您确实需要对从集合中删除的对象的接口做出假设,该怎么办? 例如,假设您想要跟踪一组Cool事。

 public interface Cool { // Reports why the object is cool void cool(); } 

然后你可能会有这样的代码:

 public static void reportCoolness(Set s) { for (Object item : s) { Cool coolItem = (Cool) item; coolItem.cool(); } } 

这不是类型安全的……你需要确保传入一个只有Cool对象的集合。 要解决它,你可能会说:

 public static void reportCoolness(Set s) { for (Cool coolItem : s) { coolItem.cool(); } } 

这很棒! 完全符合您的要求并且类型安全。 但是,如果以后你有这个:

 public interface ReallyCool extends Cool { // Reports why the object is beyond cool void reallyCool(); } 

由于所有ReallyCool对象都Cool ,您应该能够执行以下操作:

 Set s = new HashSet(); // populate s reportCoolness(s); 

但是你不能这样做,因为generics具有以下属性:假设BA的子类,则Set不是Set的子类。 对此的技术讨论是“通用类型是不变的”。 (与协变相反)。

要使最后一个示例起作用,您需要通过(安全地)转换Set中的每个元素来创建Set Set 。 为了避免让你的api的客户经历这个讨厌的,不必要的代码,你可以使reportCoolness方法更灵活,如下所示:

 public static void reportCoolness(Set s) { for (Cool coolItem : s) { coolItem.cool(); } } 

现在你的方法采用包含Cool元素或Cool任何子类的任何Set 。 所有这些类型都遵循Cool api …因此我们可以安全地对任何元素调用cool()方法

合理? 希望这可以帮助。

在第一个问题上, ListList之间的区别:

两者之间的一个显着区别是,当您使用通配符作为类型时, Collection的类型是未知的,因此add方法将引发编译时错误。

你仍然可以从List获取值,但是你需要一个显式的强制转换。