泛型编译问题:不兼容的类型

时间:2013-08-16 15:45:47

标签: java generics

鉴于这个简单的课程:

    import java.util.Collection;

    public class GenericTest<T> {
      public Collection<String> getKeys() {
        return null;
      }
      public void copy(GenericTest a_from) {
        for (String x : a_from.getKeys()) {

        }
      }
    }

我收到以下编译错误,但不明白为什么。

    error: incompatible types
    for (String x : a_from.getKeys()) {
      required: String
      found:    Object

如果我将参数更改为copy()方法为GenericTest&lt; T&gt;,则错误消失,但这不是我想要的。 copy()方法对任何类型的GenericTest都有效,而不仅仅是GenericTest&lt; T&gt;。

3 个答案:

答案 0 :(得分:2)

这不是您创建泛型类的方式。如果使用泛型类的原始类型,则在类中使用的所有参数化类型都会丢失其类型信息。因此,对于GenericTest原始类型,getKeys()方法签名更改为:

public Collection getKeys() {
    return null;
}

因此,如果您对getKeys()原始类型的GenericTest方法进行迭代,则会得到Object,而不是String,我不明白为什么您期望

来自JLS Section 4.8 - Raw Types

  

未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)M的类型是原始的在与C对应的泛型声明中对应于其类型擦除的类型。


您应该在方法中使用GenericTest<T>作为参数类型,而不是原始类型。并将getKeys的返回类型更改为Collection<T>

将您的课程更改为:

public class GenericTest<T> {
    public Collection<T> getKeys() {
      return null;
    }
    public void copy(GenericTest<T> a_from) {
      for (T x : a_from.getKeys()) {

      }
   }
}

类型T来自您为此泛型类创建的参数化类型。对于GenericTest<String>T将在您的班级中被视为String


<强>参考:

答案 1 :(得分:1)

你可能想写

public void copy(GenericTest<String> a_from) {

public void copy(GenericTest<T> a_from) {
这对我来说也很奇怪, 这里的解释(这是重复的): Why won't this generic java code compile?

答案 2 :(得分:1)

也许你想要:

public void copy(GenericTest<?> a_from) {
    for (String x : a_from.getKeys()) {

    }
}

根据您的要求,这将接受任何通用类型。

我修改了你的类,只是因为它不会返回null集合,并且我使for循环打印出读取的字符串。
这是结果,编译(并运行)就好了。

import java.util.Collection;
import java.util.ArrayList;

public class GenericTest<T> {
    public Collection<String> getKeys() {
        ArrayList<String> a = new ArrayList<String>();
        a.add("1");
        a.add("2");
        a.add("3");
        return a;
    }

    public void copy(GenericTest<?> a_from) {
        for (String x : a_from.getKeys()) {
            System.out.println(x);
        }
    }

    public static void testIt() {
        GenericTest<Integer> gti = new GenericTest<Integer>();
        GenericTest<String> gts = new GenericTest<String>();

        gts.copy(gti);
    }
}