由于'A'表达式,此代码无法编译。有趣的是:在表达式中预期
List<Foo>
泛型类型,但得到List<anonymous Foo>
(根据编译器)。它是jdk bug还是功能?
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
}
}
答案 0 :(得分:5)
第三种选择,因为我喜欢语法并且我认为它未被充分利用(可能不是那么熟知),是在方法调用上明确指定泛型参数,如下所示:
List<? extends Foo> f = <Foo>bar(new Foo(){
public void doFoo() { }
});
当你有一个明确的对象来调用方法时,它看起来更好(恕我直言),例如this.<Foo>bar(...)
。
答案 1 :(得分:4)
不,那是对的。在每种情况下,查看您传入bar
的表达式的类型。第一次,您传递的是匿名类型 - 因此返回类型为List<anonymous type>
。第二次,您传入Foo
(所以Foo
是类型参数),因此返回类型为List<Foo>
。
如果您将第一个表单更改为:
,则可以使第一个表单生效List<? extends Foo> f = bar(new Foo(){
public void doFoo() { }
});
或
List<Foo> f = bar((Foo) new Foo(){
public void doFoo() { }
});
要保留匿名类型,它与:
的区别相同List<Object> objects = bar("hello"); // Won't compile
VS
Object x = "hello";
List<Object> objects = bar(x); // Will compile
或者,正如Andrzej所示,使用显式类型参数。
答案 2 :(得分:0)
它无法编译,因为:
new Foo() {
public void doFoo() { }
}
创建一个匿名子类。这是一种不同的类型。在这种情况下,您需要明确指定类型:
List<Foo> f = bar((Foo)new Foo(){ //A
public void doFoo() { }
}); //don't compiles
答案 3 :(得分:0)
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
}
}
您已创建匿名内部类,但匿名类是外部类子类,如上所示。
恕我直言,这不是Bug或功能,而是你知道什么是发动机舱的东西;)
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
使用“双重支撑”时,会出现相同的编译错误。