传递给函数的多个参数作为联合类型

时间:2018-02-09 13:18:38

标签: java

我希望找到一种方法将多个枚举传递给方法。一种方法是

public enum State{
    A,
    B,
    C;
}
public void foo(State...states){
    // handle
}

// And call it like
foo(State.A,State.B);

但如果有一种方法可以使用多个catch子句的成语

,我很好奇
} catch (IOException | IllegalArgumentException e) {

这样你就可以像

一样调用它
foo(State.A | State.B)

我为标题道歉,但我不知道如何称呼它。请建议一个更好的标题。

修改

我不期待第一个版本已经按照我的要求做出的答案,并且第二个版本是不可能的。

我想知道为什么不可能。如果Java的语法允许使用| catch子句中的operator,为什么不能在开发中使用它。

1 个答案:

答案 0 :(得分:3)

Java语言允许您进行两种常规类型的交互:

Intersection type

可以通过方法参数的泛型类型表示:

<T extends A & B> void doSomething(T arg);

这是方法doSomething的声明期望,它的参数应该是AB的子类型。当AB中的至少一个是接口类型,并且可以通过普通的Java类直接表示时,这可以工作,例如:

interface T extends A, B { }

class T extends A implements B {

   <... implemented  methods from B ...>
}

Union type

这表示相关类型为AB。目前,这仅适用于Java中的&#34; try-multicatch&#34;:

try {
  <... a piece of code ...>
}
catch (ExceptionA | ExceptionB e) {<... handle ...>}

在此声明中,ExceptionA不需要与ExceptionB有任何关系(除了两者都是Throwable的子类之外,但这不是重点)。这个陈述也没有找到&#34;常见的超类&#34;从某种意义上说,它并没有用普通的超类型替换语句。

如果ExceptionAExceptionB都是Exception0的实例,并且有ExceptionC extends Exception0,则上面的块不会同时捕获ExceptionC,也不会{ {1}}被抛出 - 这是&#34;真正的联合类型&#34;。

在其他地方,人们可能会考虑使用联合类型是方法的返回类型。这是存在的东西,例如,Ceylon语言。它可能会来到Java,它可能不会。但是,它可以在库级别使用Either类型或技巧(如this one, for example进行模拟。

所以,尽管如此,

为什么不能宣布和使用像Enum.A |这样的东西Enum.B

这很简单:Java已经有了#34; |操作员&#34; - Bitwise OR

它不适用于Exception0,因为对于&#34;按位OR&#34;没有通用的方法。由于结构的差异而具有两个Object个实例的操作数。由于Java中的Object个实例是对象,因此该规则通常也适用。

在特定意义上,您实际上可以按位或操作使用枚举实例,但它们必须非常具体地定义:

enum

在你以这种方式定义枚举之后,考虑到你有这样的签名方法,这无疑比问题中的原始版本有点丑陋:

// basically, define a bit-mask
public enum State {
  A(0x00000001),

  B(0x00000002),

  C(0x00000004);

  private final int mask;
  public State(int mask) {
    this.mask = mask;
  }

  public int mask() { return mask; }

  public boolean isPartOf(int mask) {
    return (this.mask & mask) != 0;
  }
}

这里还有一点注意事项:如果你看一下Java中EnumSet的实现,上面的屏蔽几乎就是它内部用你的枚举值做的,除了它不要求你手动进行位掩码并使用static void doSomething(int mask) { // the method if (State.A.isPartOf(mask)) { // we got A } else <... etc. ...> } static { doSomething(State.A.mask() | State.C.mask()); } (或数组)代替long