Java中的泛型和通配符 [英] Generics and wildcards in Java
问题描述
我最近参加了一个关于泛型和通配符的Java课程。我无法理解它们之间的区别,有时甚至不需要使用它们。
I have recently taken on a Java course about generics and wildcards. I am not able to grasp the difference between them and, sometimes, even the need to use them.
两个问题,请:
1)订单包含产品清单,我们将产品单和剪辑作为产品。
1) An order has a list of products, and we have sheets and clips as products.
public class Product {}
public class Sheet extends Product{}
public class Clip extends Product{}
public class Order {
//isn't this:
private List<Product> products;
//same as this:
private List<? extends Product> products;
}
2.1)使用第一个时(列表<产品> ;
):
2.1) When using the first (List<Product>
):
public Order() {//Order constructor, trying to create an order of sheets
this.products = new ArrayList<Sheet>();//compiler asks for cast
}
如果我尝试编译而不进行转换,错误说:
if I try to compile without casting anyway, error says:
无法编译的源代码 - 不兼容类型:
java.util.ArrayList< Sheet>无法转换为
java.util.List<产品>
Uncompilable source code - incompatible types: java.util.ArrayList< Sheet > cannot be converted to java.util.List< Product >
然后如果我执行此操作:
then event if I do this:
public Order(){
products = new ArrayList<>();
products.add(new Sheet()); //again asks for a cast
}
尝试编译无论如何,错误说:
try to compile anyways, error says:
无法编译的源代码 - 错误的sym类型:java.util.List.add
Uncompilable source code - Erroneous sym type: java.util.List.add
2.2)当使用第二个( List<?extends Product>
)时:
2.2) When using the second (List<? extends Product>
):
public Order(){//订单构造函数,尝试创建工作表顺序
public Order() {//Order constructor, trying to create an order of sheets
this.products = new ArrayList<Sheet>();//compiler asks for cast as well
}
如果我尝试无论如何编译而不进行编译,错误说:
if I try to compile without casting anyway, error says:
不兼容的类型:java.util.ArrayList< Sheet>无法将
转换为java.util.List< ?扩展产品>
incompatible types: java.util.ArrayList< Sheet > cannot be converted to java.util.List< ? extends Product >
然后事件,如果我这样做:
then event if I do this:
public Order(){
products = new ArrayList<>();
products.add(new Sheet()); //no suitable method found for add(Sheet),
//method Collection.add(CAP#1) is not applicable
}
尝试编译无论如何,错误说:
try to compile anyways, error says:
无法编译的源代码 - 错误的sym类型:java.util.List.add
Uncompilable source code - Erroneous sym type: java.util.List.add
推荐答案
变量声明的类型应该匹配您在实际对象类型中传递的类型。所以:
The type of the variable declaration should match the type you pass in actual object type. So:
List<Product> list = new ArrayList<Clip>();
OR
List<Product> list = new ArrayList<Sheet>();
将无法编译。
原因在这背后,你可能最终将一个Clip对象放在一个列表中,该列表应该只包含Sheets,最终最终将其视为Sheet。
The reason behind this is that you might end up putting a Clip object in a list that was supposed to contain only Sheets and eventually end up treating it like a Sheet.
开发人员似乎感到困惑,因为在Arrays的情况下允许它。
Developers seem to get confused because it is allowed in case of Arrays.
Product[] array = new Sheet[10]; // Compiles fine
在数组的情况下允许它,因为存在阻止你的运行时异常(ArrayStoreException)在数组中放入错误类型的对象。 (考虑你为上面的数组做这个: array [0] = new Clip();
)
It's allowed in case of arrays because there's a runtime exception(ArrayStoreException) that prevents you putting a wrong type of object in the array. (Consider you do this for the above array: array[0] = new Clip();
)
这里有在列表的情况下不是等效的异常,因为JVM在运行时知道Array的类型,但由于类型擦除而不知道List的类型。
There's not equivalent exception in case of lists because JVM knows the type of Array at run time but not of List because of type erasure.
此外, private列表与LT;产品与GT;产品;
不等于私人列表<?扩展产品>产品
在某种意义上说,您可以在私有列表< Product>中添加产品的任何产品或子类型。产品;
但您不能将任何内容(除了 null
)添加到私人列表<?扩展产品>产品
。当您希望将列表传递给仅从列表中读取数据的方法时,通常会使用此语法。如下所示:
Also, private List<Product> products;
is not equivalent to private List<? extends Product> products
in the sense that you can add any product or subtype of product in private List<Product> products;
but you can't add anything (except null
) to private List<? extends Product> products
. This syntax is mostly used when you want to pass your list to a method that only reads the data from the list. Like below:
private void readProduct(List<? extends Product> list){
//read product list
}
此方法将接受 List< Clip>
和列表< Sheet>
两者。但是向它添加任何东西都会导致编译错误(除了null)。
This method will accept List<Clip>
and List<Sheet>
both. But adding anything to it will result in compilation error (except null).
这篇关于Java中的泛型和通配符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!