我即将创建一个工厂,它创建特定类型 T 的对象,它扩展了特定类 A 和另一个接口 I。但是,T 一定是未知的。以下是最低限度的声明:
public class A { }
public interface I { }
这是工厂方法:
public class F {
public static <T extends A & I> T newThing() { /*...*/ }
}
这编译得很好。
当我尝试使用该方法时,以下工作正常:
A $a = F.newThing();
...虽然这不是:
I $i = F.newThing();
编译器抱怨:
绑定不匹配:F 类型的泛型方法 newThing() 不适用于参数 ()。推断类型 I&A 不是有界参数的有效替代品
我不明白为什么。明确指出“newThing 返回某种类型 T 的东西,它确实扩展了类 A 并实现了接口 I”。当分配给 A 时一切正常(因为 T 扩展了 A)但分配给 I 却没有(因为什么?,显然返回的东西既是A又是 I)
另外:当返回一个对象时,比如说 B 类型class B extends A implements I
,我需要将它转换为返回类型 T,尽管 B 匹配边界:
<T extends A & I> T newThing() {
return (T) new B();
}
但是,编译器不会抛出 UncheckedCast 之类的任何警告。
因此我的问题是:
- 这里出了什么问题?
- 是否有一种简单的方法来实现所需的行为(即分配给静态类型 A 或 I 的变量),就像在工厂方法中通过强制转换解决返回类型问题一样?
- 为什么分配给 A 有效,而分配给 I 无效?
--
编辑:这里是完全使用 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();
}
}
编辑:这是一个完整的示例,其中包含在运行时有效的方法和调用:
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());
}
}