Java 泛型和匿名类(bug或feature?)

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>();}

由于“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>();}

    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() { }
    });
List
package最佳技巧;
导入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