说我有一个界面“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>
),则不会发生这种情况。关于如何使其发挥作用的任何建议/为什么会发生?
答案 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()
的返回类型为Iterator
,Iterator#next()
的返回类型为Object
,这是一种无法转换为String
的类型。
您需要为g1
的类型声明使用类型参数,以便它不被视为原始类型的变量。