Java泛型:有界类型参数中的多重继承<T扩展A&I>

scr*_*avy 12 java generics types bounded-wildcard

我即将创建一个工厂,它创建某种类型的对象T,它扩展了某个类A和另一个接口I.但是,T必须是未知的.以下是最低声明:

public class A { }
public interface I { }
Run Code Online (Sandbox Code Playgroud)

这是工厂方法:

public class F {
    public static <T extends A & I> T newThing() { /*...*/ }
}
Run Code Online (Sandbox Code Playgroud)

这编译所有罚款.

当我尝试使用该方法时,以下工作正常:

A $a = F.newThing();
Run Code Online (Sandbox Code Playgroud)

......虽然这不是:

I $i = F.newThing();
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

绑定不匹配:类型F的泛型方法newThing()不适用于arguments().推断的类型I和A不是有界参数的有效替代

我不明白为什么.明确指出"newThing返回某种类型的东西T,它确实扩展了A类并实现了接口I".当分配给一个一切正常(因为T延伸的),但分配给我并没有(因为什么?,清楚地返回的东西既是一个一个I)

另外:当返回一个对象时,比如说类型B class B extends A implements I,我需要将它转换为返回类型T,尽管B匹配边界:

<T extends A & I> T newThing() {
    return (T) new B();
}
Run Code Online (Sandbox Code Playgroud)

但是,编译器不会抛出任何警告,如UncheckedCast等.

因此我的问题:

  • 这里出了什么问题?
  • 是否容易实现所需的行为(即分配给静态类型A或I的变量),就像在工厂方法中通过强制转换解决返回类型问题一样?
  • 为什么分配到A工作,而我不工作?

-

编辑:这里完整的代码片段完全使用Eclipse 3.7,项目设置为JDK 6:

public class F {
    public static class A { }
    public static interface I { }

    private static class B extends A implements I {  }

    public static <T extends A & I> T newThing() {
        return (T) new B();
}

    public static void main(String... _) {
        A $a = F.newThing();
        // I $i = F.newThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个完整的示例,其中的方法和调用在运行时可以正常工作:

public class F {
    public static class A {
        int methodA() {
            return 7;
        }
    }
    public static interface I {
        int methodI();
    }

    private static class B extends A implements I {
        public int methodI() {
            return 12;
        }
    }

    public static <T extends A & I> T newThing() {
        return (T) new B();
    }

    public static void main(String... _) {
        A $a = F.newThing();
        // I $i = F.newThing();
        System.out.println($a.methodA());
    }
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*mas 10

至于第二个问题:

考虑这种情况:

 class B extends A implements I {}
 class C extends A implements I {}
Run Code Online (Sandbox Code Playgroud)

现在,以下使用类型推断:

<T extends A & I> T newThing() {
  return (T) new B();
}
Run Code Online (Sandbox Code Playgroud)

所以你可以这样称呼:

C c = F.newThing(); //T would be C here
Run Code Online (Sandbox Code Playgroud)

你看这T可能是任何扩展AI你不能只是返回的一个实例B.在上面的情况下,演员阵容可以写成(C)new B().这显然会导致异常,因此编译器会发出警告:Unchecked cast from B to T- 除非你压制这些警告.


Lou*_*man 7

这不符合您的预期. T extends A & I表明调用者可以指定任何扩展型AI,你会返回.