[英]Why can't diamond infer types on anonymous inner classes?
在Java 7及更高版本中,diamond可用于正常推断类型,因此没有问题:
List<String> list = new ArrayList<>();
但是,对于像这样的匿名内部类,它不能:
List<String> st = new List<>() { //Doesn't compile
//Implementation here
}
为什么是这样? 逻辑上在这种情况下,我绝对可以将类型推断为String
。 这个决定的逻辑原因是,在匿名内部类中实际上不能推断出类型,还是由于其他原因而省略了?
在JSR-334中 :
不支持使用带有匿名内部类的菱形,因为这样做通常需要扩展类文件签名属性以表示不可表示的类型,事实上的JVM更改。
我猜想,正如大家都知道的那样,匿名类导致了一代自己的类文件。
我想这些泛型类型不存在于这些文件中,而是由有效(静态)类型替换(因此在声明对象时由声明类型声明,如<String>
)。
实际上,对应于内部类的文件永远不会在它的多个不同实例中共享,那么为什么还要使用泛型呢? :)。
编译器强制扩展(通过为泛型添加特殊属性)强制执行这类类文件将更难以实现(并且肯定无用)。
谷歌收益率,从stackoverflow跳过帖子, http://mail.openjdk.java.net/pipermail/coin-dev/2011-June/003283.html
我猜这是这样的,通常匿名类是表观类型的具体子类
interface Foo<N extends Number>
{
void foo(N n);
}
Foo<Integer> foo = new Foo<Integer>(){ ... }
由...实施
class AnonFoo_1 implements Foo<Integer>{ ... }
Foo<Integer> foo = new AnonFoo_1();
假设我们允许对匿名类进行钻石推理,可能会出现复杂的情况
Foo<? extends Runnable> foo = new Foo<>(){ ... }
推理规则产生N=Number&Runnable
; 遵循先前的实施技巧,我们需要
class AnonFoo_2 implements Foo<Number&Runnable>{ ... }
目前不允许这样做; 超类型Foo
的类型arg必须是“普通”类型。
但是,理由不是很强烈。 我们可以发明其他实现技巧来使其工作
class AnonFoo<N extends Number&Runnable> implements Foo<N>
{
@Override public void foo(N n)
{
n.intValue();
n.run();
}
}
Foo<? extends Runnable> foo = new AnonFoo<>();
编译器应该能够做同样的技巧。
在任何情况下,至少编译器应该允许大多数不涉及“undenotable类型”的用例,如Foo<Integer> foo = new Foo<>(){...}
很可惜这些常见/简单案件也是不必要的禁止。
简而言之, <>
几乎没有推断类型,它会关闭没有它的警告。
编辑:正如@Natix指出它做了一些检查。
List<Integer> ints = new ArrayList<>();
List<String> copy = new ArrayList<>(ints);
产生编译错误
Error:Error:line (42)error: incompatible types
required: List<String>
found: ArrayList<Integer>
正如您所看到的, <>
采用了参数的类型,而不是根据copy
的类型推断出类型
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.