Java中的泛型和通配符 [英] Generics and wildcards in Java

查看:131
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆