Java 泛型和匿名类(bug或feature?)
由于“A”表达式,此代码无法编译。有趣的是:在表达式中,预期的是Java 泛型和匿名类(bug或feature?),java,generics,Java,Generics,由于“A”表达式,此代码无法编译。有趣的是:在表达式中,预期的是List泛型类型,但得到的是List(根据编译器)。这是jdk的bug还是特性 List<Foo> List<anonymous Foo> interface Foo{ void doFoo(); } public class GenericsTest { public static<V> List<V> bar(V v){ return new ArrayList<V>();}
List
泛型类型,但得到的是List
(根据编译器)。这是jdk的bug还是特性
List<Foo>
List<anonymous Foo>
interface Foo{ void doFoo(); }
public class GenericsTest {
public static<V> List<V> bar(V v){ return new ArrayList<V>();}
public static void main(String[] args) {
List<Foo> f = bar(new Foo(){ //A
public void doFoo() { }
}); //don't compiles
Foo fooImpl = new Foo(){
public void doFoo() { }
};
List<Foo> f2 = bar(fooImpl); //compiles
}
}
接口Foo{void doFoo();}
公共类泛型测试{
公共静态列表栏(V){返回新的ArrayList();}
公共静态void main(字符串[]args){
列表f=bar(新的Foo(){//A
public void doFoo(){}
});//不编译
Foo fooImpl=新的Foo(){
public void doFoo(){}
};
列表f2=bar(fooImpl);//编译
}
}
不,没错。查看每种情况下传递到bar
的表达式类型。第一次,您传入的是匿名类型-因此返回类型是List
。第二次,您传入的是Foo
(因此Foo
是类型参数),因此返回类型是List
如果将第一个表单更改为:
List<? extends Foo> f = bar(new Foo(){
public void doFoo() { }
});
List它无法编译,因为:
new Foo() {
public void doFoo() { }
}
创建一个匿名子类。这是另一种类型。在这种情况下,需要显式指定类型:
List<Foo> f = bar((Foo)new Foo(){ //A
public void doFoo() { }
}); //don't compiles
List f=bar((Foo)new Foo(){//A
public void doFoo(){}
}); //不要编译
第三种选择是显式指定方法调用上的泛型参数,因为我喜欢这种语法,而且我认为它没有得到充分利用(可能不是很广为人知),如下所示:
List<? extends Foo> f = <Foo>bar(new Foo(){
public void doFoo() { }
});
Listpackage最佳技巧;
导入java.util.ArrayList;
导入java.util.List;
接口Foo{void doFoo();}
公共类泛型测试{
公共静态列表栏(V){返回新的ArrayList();}
公共静态void main(字符串[]args){
列表f=bar(新的Foo(){//A
public void doFoo(){}
});//不编译
System.out.println(新的Foo(){//A
public void doFoo(){}
}.getClass();//类的最佳技巧。GenericsTest$1哇,现在让Eclipse自动生成或至少建议此选项。我只是内联了一个内部类,结果是随机的。没有强制转换,我喜欢。将其用于番石榴可选的可选的,也用于可选的。缺席()
。如果我没有从Andrzej那里找到答案,我会+1'd这个。也许你可以更新答案或指向Andrzej的解决方案?@owlstead:在底部添加了一条小评论。鉴于Andrzej的答案现在是最上面的答案,我认为不值得复制它或类似的东西。
new Foo() {
public void doFoo() { }
}
List<Foo> f = bar((Foo)new Foo(){ //A
public void doFoo() { }
}); //don't compiles
List<? extends Foo> f = <Foo>bar(new Foo(){
public void doFoo() { }
});
package theBestTrick;
import java.util.ArrayList;
import java.util.List;
interface Foo{ void doFoo(); }
public class GenericsTest {
public static<V> List<V> bar(V v){ return new ArrayList<V>();}
public static void main(String[] args) {
List<Foo> f = bar(new Foo(){ //A
public void doFoo() { }
}); //don't compiles
System.out.println(new Foo(){ //A
public void doFoo() { }
}.getClass());//class theBestTrick.GenericsTest$1 <- THAT'S WHY !!!
Foo fooImpl = new Foo(){
public void doFoo() { }
};
List<Foo> f2 = bar(fooImpl); //compiles
}
}
class FooImpl implements Foo{
public void doFoo() { }
}
List<FooImpl> f3 = bar(new FooImpl()); //compiles
List<FooImpl> f4 = bar(new FooImpl(){{
System.out.println("I'm anonymous inner class");}}
); // not compiles