Java Generics: 多重继承 in Bounded Type Parameters <T 扩展了 A & I>

2022-09-04 19:23:25

我即将创建一个工厂,该工厂创建特定类型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),但分配给我没有(因为是什么?,显然返回的东西既是AI)

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

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

但是,编译器不会引发任何警告,如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();
    }
}

编辑:下面是一个完整的示例,其中包含在运行时工作的方法和调用:

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

答案 1

至于第二个问题:

请考虑以下情况:

 class B extends A implements I {}
 class C extends A implements I {}

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

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

所以你可以这样称呼它:

C c = F.newThing(); //T would be C here

您会看到这可能是任何扩展的内容,并且您不能只返回 的实例。在上面的情况下,强制转换可以写为 .这显然会导致异常,因此编译器会发出警告:- 除非您抑制这些警告。TAIB(C)new B()Unchecked cast from B to T


答案 2

这不会做你期望它做的事情。 表示调用方可以指定扩展 和 的任何类型,您将返回它。T extends A & IAI