Java泛型编译器错误:类型不兼容

Java泛型编译器错误:类型不兼容,java,generics,Java,Generics,在用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 st

在用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<? 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>();
  }
}
封装测试;
导入java.util.*;
公共类TestClass{
公共静态类A扩展了C{}
公共静态类B扩展了C{}
公共静态类C{}
公共静态类D{}
公共静态类E{}
公共静态void main(字符串参数[]){

E检查Arrays.asList调用返回的对象的类型。我猜它会返回一个List也许这会帮助您理解:

    ArrayList<Object> aList = new ArrayList<String>();
ArrayList aList=new ArrayList();
这也不会编译为类似的错误

编辑: 咨询:
比这更糟糕。你甚至不能这样做:

List<D<?>> lDQ = Arrays.asList(new D<A>());

List这与之前发布的案例基本相同。基本上,在泛型案例中,您永远不允许执行此分配:

想想这个例子:

ArrayList<Object> alist = new ArrayList<Number>();
ArrayList alist=new ArrayList();
这不会编译,因为它不是类型安全的。您可能会添加字符串。您正在尝试将一个保证为数字但可以为任意数字的对象列表分配给一个只保证包含对象但可以为任意对象的列表。如果编译器允许这种情况,它将放宽对以下对象的限制:允许对象类型进入列表。这就是为什么必须使用通配符?,例如:

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

ArrayList问题是
List您不能在泛型参数中继承。假设您有以下引用:

List<Object> a;
List<String> b;
如果有人执行以下操作,会发生什么情况:

a.add(new Integer(1));
String s = b.get(0);

你会得到一个字符串列表的整数。这应该不起作用。这就是为什么列表和列表是不兼容的,尽管可以将字符串分配给对象引用。泛型不能与继承一起工作。

不。
我想如果我们扩展你的示例,这会更清楚。让我们在E中加入一些功能,并详细说明主要方法的第一行:

public static class E<T>{
    private final T thing;

    public void setThing(T thing) {
        this.thing = thing;
    }

    public T getThing() {
        return thing;
    }
}

public static void main(String[] args) {
    E<D<? extends C>> a1;
    E<D<A>> a2 = new E<D<A>>();
    a1 = a2; // this won't compile, but why?

    // these things are permissible on a1:
    a1.setThing(new D<A>());
    a2.setThing(new D<B>());

    // now let's try doing the same thing to a2:
    a2.setThing(new D<A>());
    a2.setThing(new D<B>()); // oops
}
公共静态类E{
私事;
公共无效设置(T设置){
这个;
}
公共T getting(){
归还物;
}
}
公共静态void main(字符串[]args){

E当使用非通配符通用类型
T
分配给变量(
E
)时,被分配的对象必须将
T
作为其通用类型(包括
T
的所有通用类型参数、通配符和非通配符)。在您的例子中,
T
D
,它与
D的类型不同。对于下一版本的Java谜题来说,这是一个好问题。我相信您偶然发现了一个边缘案例。非常有趣。如果您能理解它,这可能会有用:它不会编译,因为使用aList引用,您将能够插入Objects进入您的列表,但它应该只包含字符串。看看我刚刚发布的新行。为什么这不是可浇铸的?这一切归结于我对GrzegorzOledzki的答案的评论。引用将允许您使用比原始泛型类接受的范围更广的类。我尝试分配给您的方法是错误的你可能需要错误地思考:这完全是对象赋值的类型安全的反义词。无论是有意义的还是非安全的,都不会工作。泛型类型必须精确匹配,而不仅仅是扩展类型。你需要用回程键来摆脱那些角括号。我认为C++示例不利于java问题。是否有一个列表与其他事物的列表是一致的,关于理解继承和替代性。
,IMO,是关于OO基础的;因此,C++的引用应该是可接受的。这个例子仍然不正确(甚至帮助,IMO)。行不编译,allObjects.add()也不编译。我认为这个答案最能说明问题。您可以使用E
// 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>());
List<Object> a;
List<String> b;
a.add(new Integer(1));
String s = b.get(0);
public static class E<T>{
    private final T thing;

    public void setThing(T thing) {
        this.thing = thing;
    }

    public T getThing() {
        return thing;
    }
}

public static void main(String[] args) {
    E<D<? extends C>> a1;
    E<D<A>> a2 = new E<D<A>>();
    a1 = a2; // this won't compile, but why?

    // these things are permissible on a1:
    a1.setThing(new D<A>());
    a2.setThing(new D<B>());

    // now let's try doing the same thing to a2:
    a2.setThing(new D<A>());
    a2.setThing(new D<B>()); // oops
}
E<? extends D<? extends C>> a = new E<D<A>();