有界类型参数铸造问题

soc*_*qwe 6 java generics

我有一个像这样的java界面

public interface MyInterface<T> {
  public <V extends T> V get(String key, Bundle bundle);
}
Run Code Online (Sandbox Code Playgroud)

请注意方法的<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();
  }
}
Run Code Online (Sandbox Code Playgroud)

所以,当我现在有这样一个类:

class Bar {
   public Other other;

   public Other setOther(Other other);
}
Run Code Online (Sandbox Code Playgroud)

然后我想在一个实例中MyFoo设置:OtherBar

MyFoo foo = new MyFoo();
Bar bar = new Bar();
bar.other = foo.get();
Run Code Online (Sandbox Code Playgroud)

这非常有效.类型可以由java泛型确定.不需要额外的演员阵容.

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

MyFoo foo = new MyFoo();
Bar bar = new Bar();
bar.setOther(foo.get()); // Fails
Run Code Online (Sandbox Code Playgroud)

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

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

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

任何想法如何解决,而无需添加额外的演员 bar.setOther( (Other) foo.get() )

Erw*_*idt 3

在赋值中,Java 编译器通过查看要赋值的类型来知道该方法使用什么返回类型。所以回答你的问题

\n\n
\n

知道如何在不添加像\n 这样的额外演员的情况下解决这个问题吗 bar.setOther( (Other) foo.get() )

\n
\n\n

您可以通过以下方式做到这一点:

\n\n
Other value = foo.get();\nbar.setOther(value);\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
bar.setOther(foo.<Other>get());\n
Run Code Online (Sandbox Code Playgroud)\n\n

第三种选择:切换到 Java 8;在 Java 8 中你可以这样做bar.setOther(foo.get());

\n\n

对于 Java 7,这种类型推断的规则在JLS 第 15.12.2.8 节中指定:

\n\n
\n

如果任何方法的类型参数不是从实际参数的类型推断出来的,那么现在将按如下方式推断它们。

\n\n

如果方法结果出现在将进行 赋值转换 (\xc2\xa75.2) 到类型 S 的上下文中,则 [...]

\n
\n\n

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

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

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

\n