为什么不能在有界通配符泛型中拥有多个接口?

我知道Java的泛型类型有各种各样的反直觉属性。这里有一个特别我不明白的,我希望有人能向我解释。为类或接口指定类型参数时,可以对其进行绑定,以便它必须使用 实现多个接口。但是,如果您正在实例化实际对象,则不再起作用。 很好,但无法编译。请考虑以下完整代码段:public class Foo<T extends InterfaceA & InterfaceB>List<? extends InterfaceA>List<? extends InterfaceA & InterfaceB>

import java.util.List;

public class Test {

  static interface A {
    public int getSomething();
  }

  static interface B {
    public int getSomethingElse();
  }

  static class AandB implements A, B {
    public int getSomething() { return 1; }
    public int getSomethingElse() { return 2; }
  }

  // Notice the multiple bounds here. This works.
  static class AandBList<T extends A & B> {
    List<T> list;

    public List<T> getList() { return list; }
  }

  public static void main(String [] args) {
    AandBList<AandB> foo = new AandBList<AandB>(); // This works fine!
    foo.getList().add(new AandB());
    List<? extends A> bar = new LinkedList<AandB>(); // This is fine too
    // This last one fails to compile!
    List<? extends A & B> foobar = new LinkedList<AandB>();
  }
}

似乎应该很好地定义语义 - 我想不出允许两种类型的交集而不仅仅是一种类型的交集来失去类型安全性。我相信有一个解释。有人知道它是什么吗?bar


答案 1

有趣的是,接口看起来同时支持通配符 arg 的上限和下限;并且每个边界可以包含多个边界java.lang.reflect.WildcardType

Type[] getUpperBounds();
Type[] getLowerBounds();

这远远超出了语言所允许的范围。源代码中有一个隐藏的注释

// one or many? Up to language spec; currently only one, but this API
// allows for generalization.

界面的作者似乎认为这是一个偶然的限制。

你的问题的固定答案是,泛型已经太复杂了。增加更多的复杂性可能被证明是最后一根稻草。

要允许通配符具有多个上限,必须扫描规范并确保整个系统仍然有效。

我知道一个麻烦是在类型推断中。当前的推理规则根本无法处理交叉点类型。没有规则可以减少约束。如果我们将其简化为A&B << C

    A<<C 
  or
    A<<B

任何当前的推理引擎都必须经过大修才能允许这种分岔。但真正严重的问题是,这允许多种解决方案,但没有理由偏爱一种解决方案。

但是,推理对于类型安全并不重要。在这种情况下,我们可以简单地拒绝推断,并要求程序员显式填写类型参数。因此,推理困难并不是反对干预类型的有力论据。


答案 2

来自 Java 语言规范

4.9 交叉点类型 交叉点类型采用 T1 & ...& Tn, n>0,其中 Ti, 1in 是类型表达式。在捕获转换 (§5.1.10) 和类型推断 (§15.12.2.7) 的过程中会出现交集类型。不可能直接将交集类型编写为程序的一部分;没有语法支持这一点。交集类型的值是那些对象,这些对象是所有类型 Ti 的值,对于 1in。

那么为什么不支持呢?我的猜测是,你应该怎么做?- 让我们假设这是可能的:

List<? extends A & B> list = ...

那么应该做什么

list.get(0);

返回?没有用于捕获返回值 的语法。在这样的列表中添加一些东西也是不可能的,所以它基本上是无用的。A & B


推荐