Java泛型编译器错误 [英] Java generics compiler error

查看:105
本文介绍了Java泛型编译器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当用Java做一些不太奇妙的事情时,我发现泛型出现了一个错误,我无法理解它为什么不起作用。代码是:

  package test; 
import java.util。*;
public class TestClass {
public static class A extends C {}
public static class B extends C {}
public static class C {}
public static class D< ; T> {}
public static class E< T> {}

public static void main(String args []){
E< D<扩展C>> a = new E< D>>();
E< D<扩展对象>> b =新E E< D<延伸A>> c = new E< D>>();
E< D<超级A>> d = new E ();
D <?扩展C> e =新的D A();
D <?延伸A> f = new D< A>();
D <?延伸A> g = new D< A>();


$ / code>

编译时得到的错误是:

 
test / TestClass.java:11:不兼容的类型
找到了:test.TestClass.E>
required:test.TestClass .E>
E> a = new E>();
^
test / TestClass.java:12:不兼容类型
找到:test.TestClass.E>
required:test.TestClass.E>
E> b = new E>();
^
test / TestClass.java:13:不兼容类型
找到:test.TestClass.E>
required:test.TestClass.E>
E> c = new E>();
^
test / TestClass.java:14:不兼容类型
找到:test.TestClass.E>
required:test.TestClass.E>
E> d = new E>();
^
4错误

如果 E ,那肯定应该匹配 E< D<扩展对象>> ,对吧?或者我错过了什么?

解决方案

这与之前发布的案例基本相同。基本上,在一个泛型案例中,你绝不允许这样做:



想想这个例子:

 的ArrayList<对象> alist = new ArrayList< Number>(); 

这不会编译,因为它不是类型安全的。你可能会添加字符串aList。您正尝试将保证为数字但可以是任何数字的对象列表分配给仅保证包含对象但可以是任何对象的列表。如果编译器允许这种情况,它将放宽允许哪些类型的对象进入列表的限制。这就是为什么你必须使用通配符的原因:

  ArrayList<扩展对象> alist = new ArrayList< Number>(); 

给编译器 ArrayList <? extends Object> ,意思是某种特定类型的ArrayList?',我不知道,但是我知道它扩展了Object,这个ArrayList保证只包含这个未知'?'的元素。类型,因此只包含对象。在这种情况下,编译器将不允许你执行alist.add(2)。为什么会出现这种情况,因为编译器不知道列表元素的类型,并且不能保证你可以插入Integer对象。



你认为 D <? extends Object> D< ;?的超类型扩展C> 。但是,列表< D< extends Object>> 不是 List< D<的子类型扩展C>> ,你应该使用 List<扩展D <?延伸C>>



您的情况基本上相当于

 的ArrayList< d< ;?扩展对象>> alist = new ArrayList< D<扩展C>>(); 

你有和上面相同的问题,右边的列表只能包含类的对象D的参数类型为C,并且您试图将其分配给列表(在左侧)可以包含类型D的对象,其类型参数可以是任何对象。



  ArrayList< D< p< p>如果编译器允许你的代码不是类型安全的,那么下面的代码就会失败。 ?扩展对象>> alist = new ArrayList< D<扩展C>>(); //<不是类型安全的
alist.add(new D< Number>); //< oops

总之,您需要具体示例如下:

  //左侧的类型参数是?扩展子类型
List< ;?扩展D <?扩展对象>> b = Arrays.asList(new D<(>),new D< B>);

//左侧的类型参数是相同的
List< D<扩展C>> b = Arrays.asList(new D<(>),new D< B>);

//左侧的类型参数是?扩展子类型
List< ;?扩展D <?扩展C>> c = Arrays.asList(new D< A>());

//左侧的类型参数相同
List< D< A>> c = Arrays.asList(new D< A>());

希望这有助于您。


When doing some not really fancy things with Java, I came over an error with generics that I was not able to understand why it doesn't work. The code is:

package test;
import java.util.*;
public class TestClass {
  public static class A extends C{}
  public static class B extends C{}
  public static class C{}
  public static class D<T>{}
  public static class E<T>{}

  public static void main(String args[]){
      E<D<? extends C>> a = new E<D<A>>();
      E<D<? extends Object>> b = new E<D<? extends C>>();
      E<D<? extends A>> c = new E<D<A>>();
      E<D<? super A>> d = new E<D<A>>();
      D<? extends C> e = new D<A>();
      D<? extends A> f = new D<A>();
      D<? extends A> g = new D<A>();
  }
}

The error I get when compiling is:

test/TestClass.java:11: incompatible types
found   : test.TestClass.E>
required: test.TestClass.E>
      E> a = new E>();
                            ^
test/TestClass.java:12: incompatible types
found   : test.TestClass.E>
required: test.TestClass.E>
      E> b = new E>();
                                 ^
test/TestClass.java:13: incompatible types
found   : test.TestClass.E>
required: test.TestClass.E>
      E> c = new E>();
                            ^
test/TestClass.java:14: incompatible types
found   : test.TestClass.E>
required: test.TestClass.E>
      E> d = new E>();
                          ^
4 errors

If E<D<? extends C>> is found, that should surely match E<D<? extends Object>>, right? Or have I missed something?

解决方案

This is basically the same case as posted previous. Basically, in a generics case, you are never allowed to do this assigment:

Think of this example:

ArrayList<Object> alist = new ArrayList<Number>();

This doesn't compile because it is not type safe. You could possibly add Strings aList. You are trying to assign a list of objects that are guaranteed to be Numbers but can be any Number, to a list that only guarantees you to contain objects but that can be any objects. If the compiler allowed this case it would loosen the restriction on which types of objects are allowed to get into the list. This is why you must use the wildcard ?, as such:

ArrayList<? extends Object> alist = new ArrayList<Number>();

To the compiler ArrayList<? extends Object>, means "an ArrayList of some specific type '?' that I don't know, but which I know extends Object. This ArrayList is guaranteed to contain only elements of this unknown '?' type, and therefore contains only objects". In this case the compiler will however not allow you to do alist.add(2). Why is that the case, because the compiler doesn't know the type of the elements of the list, and can't guarantee that you are allowed to insert Integer objects into it.

You are right in thinking that D<? extends Object> is a supertype of D<? extends C>. However, List<D<? extends Object>> is not a subtype of List<D<? extends C>>, you should be using List<? extends D<? extends C>>.

Your case is basically equivalent to

ArrayList<D<? extends Object>> alist = new ArrayList<D<? extends C>>();

You have the same problem as above, the list on the right hand side can only contain object of class D whose type Parameter is C, and you are trying to assign it to a list (on the left hand side) can contain objects of class D whose type parameter can be any object.

So if the compiler allowed your code would not be type safe, and the following would fail.

ArrayList<D<? extends Object>> alist = new ArrayList<D<? extends C>>(); //< not type safe
alist.add(new D<Number>); //< oops

In short, what you need for your specific example is the following:

// type parameter of left hand side is ? extends subtype
List<? extends D<? extends Object>> b = Arrays.asList(new D<A>(), new D<B>()); 

// type parameter of left hand side is identical
List<D<? extends C>> b = Arrays.asList(new D<A>(), new D<B>());

// type parameter of left hand side is ? extends subtype
List<? extends D<? extends C>> c = Arrays.asList(new D<A>());

// type parameter of left hand side is identical
List<D<A>> c = Arrays.asList(new D<A>());

Hope this helps.

这篇关于Java泛型编译器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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