为什么在有界通配符泛型中不能有多个接口? [英] Why can't you have multiple interfaces in a bounded wildcard generic?

查看:20
本文介绍了为什么在有界通配符泛型中不能有多个接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 Java 的泛型类型有各种违反直觉的属性.这是我特别不明白的一个,我希望有人可以向我解释.为类或接口指定类型参数时,可以绑定它,使其必须实现多个接口,其中 public class Foo<T extends InterfaceA &界面B>.但是,如果您正在实例化一个实际对象,这将不再起作用.<代码>列表 很好,但是 List 编译失败.考虑以下完整片段:

I know there's all sorts of counter-intuitive properties of Java's generic types. Here's one in particular that I don't understand, and which I'm hoping someone can explain to me. When specifying a type parameter for a class or interface, you can bound it so that it must implement multiple interfaces with public class Foo<T extends InterfaceA & InterfaceB>. However, if you're instantiating an actual object, this doesn't work anymore. List<? extends InterfaceA> is fine, but List<? extends InterfaceA & InterfaceB> fails to compile. Consider the following complete snippet:

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 的语义应该是明确定义的——我想不出通过允许两种类型而不是一种类型的交集来损失类型安全性.我确定有一个解释.有人知道是什么吗?

It seems the semantics of bar should be well-defined -- I can't think of any loss of type-safety by allowing an intersection of two types rather than just one. I'm sure there's an explanation though. Does anyone know what it is?

推荐答案

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

Interestingly, interface java.lang.reflect.WildcardType looks like it supports both upper bounds and lower bounds for a wildcard arg; and each can contain multiple bounds

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

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

This is way beyond what the language allows. There's a hidden comment in the source code

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

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

The author of the interface seems to consider that this is an accidental limitation.

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

The canned answer to your question is, generics is already too complicated as it is; adding more complexity might prove to be the last straw.

要允许通配符具有多个上限,必须仔细浏览规范并确保整个系统仍然有效.

To allow a wildcard to have multiple upper bounds, one has to scan through the spec and make sure the entire system still works.

我知道的一个问题是类型推断.当前的推理规则根本无法处理交集类型.没有规则可以减少约束 A&B <<C.如果我们把它减少到

One trouble I know would be in the type inference. The current inference rules simply can't deal with intersection types. There's no rule to reduce a constraint A&B << C. If we reduced it to

    A<<C 
  or
    A<<B

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

any current inference engine has to go through major overhaul to allow such bifurcation. But the real serious problem is, this allows multiple solutions, but there's no justification to prefer one over another.

然而,推断对于类型安全并不是必不可少的;在这种情况下,我们可以简单地拒绝推断,并要求程序员明确填写类型参数.因此,推理困难并不是反对拦截类型的有力论据.

However, inference is not essential to type safety; we can simply refuse to infer in this case, and ask programmer to explicitly fill in type arguments. Therefore, difficulty in inference is not a strong argument against intercection types.

这篇关于为什么在有界通配符泛型中不能有多个接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆