了解java泛型中通配符的使用?

了解java泛型中通配符的使用?,java,generics,wildcard,Java,Generics,Wildcard,我问了一个类似的问题,这是一个更具体的版本,希望得到一个明确的答案。 在试图理解java泛型类型和通配符“”的用法时,我尝试了以下方法: List<Integer> li4 = new ArrayList<Integer>(); li4.add(new Integer(5)); Integer myInt4 = li4.get(0); li = li4; 以上代码编译并运行良好。 但当我尝试时: li.add(new Integer(5)); 我发现以下编译

我问了一个类似的问题,这是一个更具体的版本,希望得到一个明确的答案。 在试图理解java泛型类型和通配符“”的用法时,我尝试了以下方法:

List<Integer> li4 = new ArrayList<Integer>();
  li4.add(new Integer(5));
  Integer myInt4 = li4.get(0);
li = li4;
以上代码编译并运行良好。 但当我尝试时:

li.add(new Integer(5));
我发现以下编译错误(使用Oracle JDeveloper作为IDE):


”“是吗?“扩展整数”应允许任何扩展整数的类型。它的行为类似于“get”方法,其中它返回一个整数。同样,当ArrayList被分配给它时,它也不会抱怨。因此,例如
“li=new ArrayList()”
不会编译。那么,为什么允许我分配另一个
ArrayList()
,返回一个整数,但不添加整数?

?扩展整数
并不意味着“应该允许任何扩展整数的类型”。这意味着这是一个扩展整数的特定
T
列表


那么你从
列表中得到了什么?扩展整数
并不意味着“应该允许任何扩展整数的类型”。这意味着这是一个扩展整数的特定
T
列表


因此,从
列表中得到的任何信息都有助于我理解答案:

    List<Exception> exL = new ArrayList<Exception>();
    exL.add(new Exception());
    Exception ex = exL.get(0);
    Throwable th = exL.get(0);
    exL.add(new NullPointerException());
   /** Error(153,7):  cannot find method add(java.lang.Exception)
    exL.add(new Throwable());
   **/
List exL=new ArrayList();
添加(新异常());
异常ex=exL.get(0);
一次性th=exL.get(0);
添加(新的NullPointerException());
/**错误(153,7):找不到方法add(java.lang.Exception)
添加(新的可丢弃的());
**/
所以,当我们声明List时,元素必须至少具有异常行为,即Exception、RuntimeException及其子类。可以将从此类列表返回的元素分配给Exception或其任何子类。“异常e=exL.get(0)”或“Throwable th=exL.get(0)”。向列表中添加一个Exception实例或说NullPointerException也是可以的

List genExcepList,可以是列表、列表或列表,因为“?扩展异常”表示异常及其所有子类。事实上,List是List、List等的超类。对于这些列表类型中的任何一种,“get”调用返回的元素都保证是Exception类型。所以可以这样做:异常e=genExcepList.get(0)。但是调用genExcepList是不合适的。add(exception)as List必须满足它允许的每种类型的限制,即List、List、List等。唯一有效的是genExcepList。add(null)as“null”适用于每种类型。 另一方面,如果我们有以下情况: List rtgs=new ArrayList();
“超级异常”表示异常及其任何超类。所以列表代表列表,列表和列表。在这些列表类型中,可以调用“add(new Exception());”,因此可以调用rtgs.add(new Exception()),因为异常也是一个可丢弃的对象。但是,调用“Exception ex=rtgs.get(0)”是不合适的,因为从列表返回的元素可以是Exception、Throwable和Object中的任意一个。因此,唯一可以安全工作的是“Object ex=rtgs.get(0)”。

以下代码帮助我理解了答案:

    List<Exception> exL = new ArrayList<Exception>();
    exL.add(new Exception());
    Exception ex = exL.get(0);
    Throwable th = exL.get(0);
    exL.add(new NullPointerException());
   /** Error(153,7):  cannot find method add(java.lang.Exception)
    exL.add(new Throwable());
   **/
List exL=new ArrayList();
添加(新异常());
异常ex=exL.get(0);
一次性th=exL.get(0);
添加(新的NullPointerException());
/**错误(153,7):找不到方法add(java.lang.Exception)
添加(新的可丢弃的());
**/
所以,当我们声明List时,元素必须至少具有异常行为,即Exception、RuntimeException及其子类。可以将从此类列表返回的元素分配给Exception或其任何子类。“异常e=exL.get(0)”或“Throwable th=exL.get(0)”。向列表中添加一个Exception实例或说NullPointerException也是可以的

List genExcepList,可以是列表、列表或列表,因为“?扩展异常”表示异常及其所有子类。事实上,List是List、List等的超类。对于这些列表类型中的任何一种,“get”调用返回的元素都保证是Exception类型。所以可以这样做:异常e=genExcepList.get(0)。但是调用genExcepList是不合适的。add(exception)as List必须满足它允许的每种类型的限制,即List、List、List等。唯一有效的是genExcepList。add(null)as“null”适用于每种类型。 另一方面,如果我们有以下情况: List rtgs=new ArrayList();
“超级异常”表示异常及其任何超类。所以列表代表列表,列表和列表。在这些列表类型中,可以调用“add(new Exception());”,因此可以调用rtgs.add(new Exception()),因为异常也是一个可丢弃的对象。但是,调用“Exception ex=rtgs.get(0)”是不合适的,因为从列表返回的元素可以是Exception、Throwable和Object中的任意一个。因此,唯一可以安全工作的是“Object ex=rtgs.get(0)”。

您提到的“对于某个扩展整数的特定T”。如果该特定T扩展整数,则“T”必须至少具有在整数中找到的行为。这是真的,但它可能具有更多行为。因此,如果您尝试将一个普通的
Integer
添加到您提到的“扩展Integer的某个特定T”列表中。如果该特定T扩展Integer,则“T”必须至少具有在Integer中找到的行为。这是真的,但它可能具有更多行为。因此,如果您尝试只向
列表添加一个普通的
整数
List<? extends Number> list1 = new ArrayList<Integer>();
List<? extends Number> list2 = new ArrayList<Double>();
    List<Exception> exL = new ArrayList<Exception>();
    exL.add(new Exception());
    Exception ex = exL.get(0);
    Throwable th = exL.get(0);
    exL.add(new NullPointerException());
   /** Error(153,7):  cannot find method add(java.lang.Exception)
    exL.add(new Throwable());
   **/