Java泛型中使用通配符或有界类型参数是啥?
Posted
技术标签:
【中文标题】Java泛型中使用通配符或有界类型参数是啥?【英文标题】:What are the usage wildcard or Bounded type parameters in Java Generics?Java泛型中使用通配符或有界类型参数是什么? 【发布时间】:2014-03-13 16:44:00 【问题描述】:我一直将 java 泛型与现有的集合 API 一起使用,并且知道它提供了编译时类型安全性。
但我对在我的类中使用通配符或有界类型参数感到困惑。当编译器类型擦除实际上用基本类型替换它时,有人可以澄清使用这些的优点。为什么我们不应该将代码指向基类
作为 java 教程中的一个例子 (http://docs.oracle.com/javase/tutorial/java/generics/genMethods.html)
你可以写一个通用的方法来绘制不同的形状:
public static <T extends Shape> void draw(T shape) /* ... */
Java 编译器将 T 替换为 Shape:
public static void draw(Shape shape) /* ... */
那么为什么不直接写取Shape参数,使用通配符或者有界类型有什么好处呢?
【问题讨论】:
无,在这种特殊情况下。如果您要返回,比如说,List<T>
,那么情况会有所不同。
尝试使用List<T>
和List<Shape>
并将List<Circle>
传递给这两种方法。
有些事情你可以用泛型绑定类型做,而你不能只用基本接口做;例如,您可以专门从方法返回 T
类型的对象(否则您将仅限于返回基接口并强制转换为子类)。还有以前的 cmets 所说的,例如List<T>
.
顺便说一句:“Java 编译器将 T 替换为 Shape”。它不是。它用您传递的任何子类型替换它,它只是强制该类型是Shape
的子类型。
【参考方案1】:
在你的例子中绝对没有任何好处。
考虑以下方法签名
public static <T extends Shape> void draw(List<T> shapes) /* ... */
我可以做到以下几点
final List<Circle> circles = /* ... */
final List<Square> squares = /* ... */
draw(squares);
draw(circles);
这是我做不到的
public static void draw(List<Shape> shapes) /* ... */
这对于PECS 类型的情况尤其重要。
【讨论】:
我喜欢这个答案,就像@Rohit 一样。但这不是因为泛型的限制不支持多态性,如果想使用 ListShape
集合的方法,我希望它能够接受子类型的集合。我必须声明一个有界通配符才能允许这种行为。
对不起,我的英语语法不好,它不是我的母语;)。但我想我明白了你的意思,通配符/有界类型用于在超类型集合下吸引子类型。非常感谢您对我的耐心。【参考方案2】:
使用泛型,代码是类型安全的,您的集合也是类型安全的。这意味着更多的问题将在编译时而不是运行时被发现。
没有泛型,
一个 ArrayList 将是一个对象类型的 ArrayList,这意味着你可以在其中放入任何东西。
泛型允许您确保放入 ArrayList 中的任何内容都是特定类型。例如,如果您想创建一个 ArrayList,您只能放入 Cars 对象,而不能放入其他任何东西。
只是您真正想要的任何内容的占位符。如果您的程序只想创建汽车的 ArrayList 而从不创建不同的类型,您可以轻松地在整个程序中使用占位符而不是 E。
问题是,重要的是能够创建不同的类型并对所有不同类型的对象执行不同的操作,因此创建 ArrayList 的类通常是 E 用于“元素”,然后在您的其他类中,您将创建特定类型。
关于您的问题>>>>查看此链接Java: bounded wildcards or bounded type parameter?
【讨论】:
以上是关于Java泛型中使用通配符或有界类型参数是啥?的主要内容,如果未能解决你的问题,请参考以下文章