Java泛型编译器错误:类型不兼容 [英] Java generics compiler error: incompatible types

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

问题描述

当用Java做一些不太理想的事情时,我遇到了一个泛型错误,我无法理解为什么它不起作用.代码是:

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>();
  }
}

编译时出现的错误是:


test/TestClass.java:11: incompatible types
found   : test.TestClass.E<test.TestClass.D<test.TestClass.A>>
required: test.TestClass.E<test.TestClass.D<? extends test.TestClass.C>>
      E<D<? extends C>> a = new E<D<A>>();
                            ^
test/TestClass.java:12: incompatible types
found   : test.TestClass.E<test.TestClass.D<? extends test.TestClass.C>>
required: test.TestClass.E<test.TestClass.D<? extends java.lang.Object>>
      E<D<? extends Object>> b = new E<D<? extends C>>();
                                 ^
test/TestClass.java:13: incompatible types
found   : test.TestClass.E<test.TestClass.D<test.TestClass.A>>
required: test.TestClass.E<test.TestClass.D<? extends test.TestClass.A>>
      E<D<? extends A>> c = new E<D<A>>();
                            ^
test/TestClass.java:14: incompatible types
found   : test.TestClass.E<test.TestClass.D<test.TestClass.A>>
required: test.TestClass.E<test.TestClass.D<? super test.TestClass.A>>
      E<D<? super A>> d = new E<D<A>>();
                          ^
4 errors

如果找到了E<D<? extends C>>,那肯定应该匹配E<D<? extends Object>>,对吗?还是我错过了什么?

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:

考虑以下示例:

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

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

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>();

对于编译器ArrayList<? extends Object>,表示某种特定类型'?'的ArrayList".我不知道,但是我知道哪个扩展了Object.保证此ArrayList仅包含此未知'?'的元素.类型,因此仅包含对象".但是,在这种情况下,编译器将不允许您执行alist.add(2).为什么会这样,因为编译器不知道列表元素的类型,并且不能保证允许将Integer对象插入其中.

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.

您正确地认为D<? extends Object>D<? extends C>的超类型.但是,List<D<? extends Object>>不是List<D<? extends C>>的子类型,应该使用List<? extends D<? extends C>>.

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>>.

您的案子基本上等于

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

您遇到与上述相同的问题,右侧列表只能包含类型为Parameter的D类对象,并且您试图将其分配给列表(左侧)可以包含D类的对象,其类型参数可以是任何对象.

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>());

希望这会有所帮助.

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

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