我有几个对象都实现了需要映射到的具体接口 Op 任意类型。我正试图用双调度方法解决问题:
interface Mapper<R> {
R process(Op1 op1);
R process(Op2 op2);
}
interface Op<T>{
<R> R process(Mapper<R> mapper);
}
class Op1 implements Op<String> {
@Override
public <R> R process(Mapper<R> mapper) {
return mapper.process(this);
}
}
class Op2 implements Op<String> {
@Override
public <R> R process(Mapper<R> mapper) {
return mapper.process(this);
}
}
我创建了一个mapper,其中包含指定 Ops 的方法,映射到 String :
Mapper<String> mapper = new Mapper<String>() {
@Override
public String process(Op1 op1) {
return "1";
}
@Override
public String process(Op2 op2) {
return "2";
}
};
当我尝试将 Op 映射到 String 时:
Op op = new Op1();
String i = op.process(mapper);
进程的返回类型是 Object 而不是 String 。如果我更改 Op 界面,删除泛型,代码就像预期的那样:
interface Op{
<R> R process(Mapper<R> mapper);
}
为什么编译器不接受 Op 接口中的泛型定义?
答案 0 :(得分:5)
将Op1
分配给Op
类型的变量时,您使用的是原始类型。 Op
是通用的,但您没有提供泛型类型参数,因此会发生类型擦除,返回类型为Object
,而不是String
。您确实创建了一个Op1
Op<String>
,但在分配给原始Op
时该信息会丢失。
当在方法而不是接口上声明泛型类型参数时,它起作用,因为类型推断接管并且R
被推断为String
。
为了使接口本身具有通用性,只需要在Op
变量上提供泛型类型参数。毕竟,Op1
是Op<String>
。
Op<String> op = new Op1();