2013-08-16 51 views
1

鉴于这种简单的类:泛型编译问题:不兼容的类型

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 <牛逼>,但是这不是我想要的。 copy()方法在任何类型的GenericTest上都有效,不仅仅是GenericTest <T>。

+0

'a_from'声明在哪里? – christopher

+1

a_from在copy()方法的签名中声明 – Mitch

回答

2

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

public Collection getKeys() { 
    return null; 
} 

所以,如果你遍历GenericTest原始类型的getKeys()方法,你会得到Object,而不是String,我不明白为什么你的期望。

JLS Section 4.8 - Raw Types

的类型构造函数(§8.8)的,实例方法(8.4节,第9.4节),或者非静态字段(§8.3)原始C型的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从你创建这个通用类,参数化类型infered。对于GenericTest<String>,T将作为String,在你的班级。


参考:

+0

但getKeys()方法确实返回String的集合,而不是T.(此处的示例从我的实际类中削减,仅显示错误条件。 ) – Mitch

+0

@Mitch。在这种情况下,使用'GenericTest '作为方法参数。但我没有看到任何理由让你的类变得通用。 –

+0

我的困惑是编译器改变了getKeys()方法的返回类型,尽管我希望它是String。只是去显示总是有更多的学习! – Mitch

1

你可能想写

public void copy(GenericTest<String> a_from) { 

public void copy(GenericTest<T> a_from) { 

这看起来奇怪,我也一样,这里 解释(这是一式两份): Why won't this generic java code compile?

+0

查看我的原帖。 copy()方法适用于任何类型的GenericTest,而不仅仅是类型T. – Mitch

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