为什么不能在匿名内部类上使用菱形推断类型?

在Java 7及更高版本中,菱形可用于正常推断类型,因此没有问题:

List list = new ArrayList(); 

但是,对于像这样的匿名内部类,它不能:

 List st = new List() { //Doesn't compile //Implementation here } 

为什么是这样? 从逻辑上讲,在这种情况下,我绝对可以将类型推断为String 。 这个决定的逻辑原因是,在匿名内部类中实际上不能推断出类型,还是由于其他原因而省略了?

在JSR-334中 :

不支持将菱形与匿名内部类一起使用,因为这样做通常需要扩展类文件签名属性以表示不可表示的类型,事实上的JVM更改。

我猜想,正如大家都知道的那样,匿名类导致了一代自己的类文件。

我认为generics类型不存在于这些文件中,而是由有效(静态)类型替换(因此在声明对象时由声明类型声明,如 )。

实际上,对应于内部类的文件永远不会在它的多个不同实例中共享,那么为什么要将generics纳入其中呢?! :)。

编译器强制扩展(通过为generics添加特殊属性)到这类类文件将更难以实现(并且肯定无用)。

谷歌收益率,从stackoverflow跳过post, http://mail.openjdk.java.net/pipermail/coin-dev/2011-June/003283.html

我猜这是这样的,通常匿名类是表观类型的具体子类

  interface Foo { void foo(N n); } Foo foo = new Foo(){ ... } 

由…实施

  class AnonFoo_1 implements Foo{ ... } Foo foo = new AnonFoo_1(); 

假设我们允许对匿名类进行钻石推理,可能会有复杂的情况

  Foo foo = new Foo<>(){ ... } 

推理规则产生N=Number&Runnable ; 按照以前的实施技巧,我们需要

  class AnonFoo_2 implements Foo{ ... } 

目前不允许这样做; 超类型Foo的类型arg必须是“普通”类型。


但是,理由不是很强。 我们可以发明其他实现技巧来使其工作

  class AnonFoo implements Foo { @Override public void foo(N n) { n.intValue(); n.run(); } } Foo foo = new AnonFoo<>(); 

编译器应该能够做同样的技巧。

在任何情况下,至少编译器应该允许大多数不涉及“undenotable类型”的用例,如Foo foo = new Foo<>(){...}很可惜这些常见/简单案件也是不必要的禁止。

简而言之, <>几乎没有推断类型,它会关闭没有它的警告。

编辑:正如@Natix指出它做了一些检查。

 List ints = new ArrayList<>(); List copy = new ArrayList<>(ints); 

产生编译错误

 Error:Error:line (42)error: incompatible types required: List found: ArrayList 

正如您所看到的, <>采用了参数的类型,而不是根据copy的类型推断出类型