集合类型参数隐藏在Java中的通用接口中的其他方法上

时间:2013-12-10 02:04:29

标签: java generics

说我有一个界面“Generic” -

public interface Generic<T> {
    public T echo(T input); 
    public List<String> hello();    
}

一个实现类说GenericImpl有任何简单的实现。现在,当我创建Generic的实例并调用hello时,它会返回List而不是List<String> -

 Generic g1 = new GenericImpl();
 for (String msg : g1.hello()) {  // Gives compilation error : 
  // Type mismatch, cannot convert from element type Object to String
 ...

即使在eclipse中,当我将鼠标悬停在g1.hello上时,它会将返回类型显示为List而不是List<String>

如果我使用普通接口(没有通用<T>),则不会发生这种情况。关于如何使其发挥作用的任何建议/为什么会发生?

2 个答案:

答案 0 :(得分:3)

您必须将接口定义为通用接口(带有类型)。

Generic<YourGenericType> g1 = new GenericImpl();

通过省略通用定义,它将被视为“原始类型”。原始类型将返回Objects。有关原始类型的更多信息可以在here找到。

public class Test {
    public static void main(String[] args) {
        Generic<Integer> obj = new GenericImpl();
        System.out.println(obj.echo(5));
        for(String s : obj.hello()){
            System.out.println(s);
        }
    }
}

interface Generic<T> {
    public T echo(T input); 
    public List<String> hello();    
}

class GenericImpl implements Generic<Integer> {
    @Override
    public Integer echo(Integer input) {
        return input;
    }

    @Override
    public List<String> hello() {
        return new ArrayList<String>(Arrays.asList("lala", "lolo"));
    }   
}

输出:

  

5
  拉拉
  洛洛

答案 1 :(得分:3)

这与原始类型有关。首先是definition

  

为了便于与非通用遗留代码连接,可以实现   使用参数化类型(第4.5节)的擦除(第4.6节)作为类型   删除元素类型为a的数组类型(第10.1节)   参数化类型。这种类型称为原始类型。

你在这里使用这种原始类型

Generic g1 = new GenericImpl();

因为Generic没有类型参数。然后JLS也说明了

  

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

因此,在使用原始类型Generic时,hello()方法的返回类型为List,这是List<String>的删除。因此,List#iterator()的返回类型为IteratorIterator#next()的返回类型为Object,这是一种无法转换为String的类型。

您需要为g1的类型声明使用类型参数,以便它不被视为原始类型的变量。