泛型和匿名类(错误或功能?)

时间:2009-10-29 10:46:02

标签: java generics

由于'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
    }
}
 

4 个答案:

答案 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

使用“双重支撑”时,会出现相同的编译错误。