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

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

问题描述

我知道Java的泛型类型有各种反直觉的属性。这里有一个特别的,我不明白,我希望有人可以向我解释。为类或接口指定类型参数时,可以将其绑定,以便它必须使用 public class Foo< T extends InterfaceA& InterfaceB> 。但是,如果你正在实例化一个实际的对象,这不再适用。 列表与LT ;?扩展InterfaceA> 很好,但是 List< ;?扩展了InterfaceA& InterfaceB> 无法编译。考虑下面的完整片段:

  import java.util.List; 

public class Test {

static interface A {
public int getSomething();
}

静态接口B {
public int getSomethingElse();
}

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

//注意这里的多重界限。这工作。
static class AandBList< T extends A& B个{
列表< T>列表;

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

public static void main(String [] args){
AandBList< AandB> foo = new AandBList< AandB>(); //这工作正常!
foo.getList()。add(new AandB());
列表< ;?延伸A> bar = new LinkedList< AandB>(); //这也很好
//最后一个编译失败!
列表< ;?扩展A& B个foob​​ar = new LinkedList< AandB>();


$ / code>

看来 bar 应该是明确定义的 - 我不能想到任何类型安全性的损失,只允许两种类型的交集,而不仅仅是一种。但我确定有一个解释。有人知道它是什么吗?

解决方案

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

 类型[] getUpperBounds(); 
键入[] getLowerBounds();

这超出了语言允许的范围。源代码中有隐藏的评论

  //一个或多个?达到语言规范;目前只有一个,但是这个API 
//允许泛化。

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



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



为了让通配符有多个上限,必须扫描规范并确保整个系统仍然作品。



我知道的一个麻烦是类型推断。目前的推断规则根本无法处理截取类型。没有规则来减少约束 A& B<< ç。如果我们把它减少到

  A 
A <

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

然而,推论对于类型安全来说并不重要,在这种情况下,我们可以拒绝推断,并要求程序员明确填写类型参数。因此,推断困难并不是反对截获类型的强有力论据。

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

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?

解决方案

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.

One trouble I know would be in the type inference. The current inference rules simply can't deal with intercection 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天全站免登陆