有界类型参数铸造问题

时间:2015-12-28 13:14:15

标签: java generics

我有一个像这样的java界面

public interface MyInterface<T> {
  public <V extends T> V get(String key, Bundle bundle);
}

请注意方法的<V extends T>类型参数。

然后我有一个班级MyFoo implements MyInterface

class MyFoo implements MyInterface<Object> { // Object because can be any type

  @Override public <V> V get(String key, Bundle bundle) {
    return new Other();
  }
}

所以当我现在有这样一个班级时:

class Bar {
   public Other other;

   public Other setOther(Other other);
}

然后我想MyFooOther个实例中设置Bar

MyFoo foo = new MyFoo();
Bar bar = new Bar();
bar.other = foo.get();

这完美无缺。类型可以由java泛型确定。不需要额外的演员阵容。

但是,如果我想使用bar.setOther(),则无法确定类型:

MyFoo foo = new MyFoo();
Bar bar = new Bar();
bar.setOther(foo.get()); // Fails

然后我得到以下编译错误:

  

错误:不兼容的类型:对象无法转换为其他

我不明白为什么这对bar.setOther( foo.get() )方法不起作用,但在直接访问字段时有效bar.other = foo.get()

任何想法如何解决这个问题而不添加像bar.setOther( (Other) foo.get() )

这样的额外演员

1 个答案:

答案 0 :(得分:3)

在赋值中,Java编译器通过查看分配给它的类型来了解要用于该方法的返回类型。所以回答你的问题

  

任何想法如何解决这个问题而不添加额外的演员表   bar.setOther( (Other) foo.get() )

这是您可以这样做的方式:

Other value = foo.get();
bar.setOther(value);

还有另一种方式,看起来更糟,但仍然没有演员:

bar.setOther(foo.<Other>get());

还有第三种选择:切换到Java 8;在Java 8中,您可以bar.setOther(foo.get());

对于Java 7,此类型推断的规则在JLS section 15.12.2.8

中指定
  

如果没有从类型中推断出任何方法的类型参数   实际的论点,现在推断如下。

     

如果方法结果发生在受其影响的上下文中   分配转换(第5.2节)到类型S,然后是[...]

如果在赋值表达式中使用方法结果,则该方法结果将进行赋值转换。

  
      
  • 否则,通过调用来推断未解析的类型参数   在本节描述的程序中假设的   方法结果已分配给Object类型的变量。
  •   

如果在结果未在赋值表达式中使用的方法中使用了未解析的类型参数,则将类型参数解释为将方法结果分配给类型为Object的变量。所以这意味着在这种情况下,如果get()方法的结果未分配给变量,则get()方法的返回类型将被视为Object