20

是否可以将 Java 中的对象转换为组合的泛型类型?

我有这样的方法:

public static <T extends Foo & Bar> void doSomething(T object) {
    //do stuff
}

如果我有一个实现两个接口(Foo & Bar)的类,调用这个方法是没有问题的。

问题是当我需要调用此方法时,我需要传递给它的对象被接收为java.lang.Object,我需要对其进行强制转换以使编译器满意。但我不知道如何制作这个演员表。

编辑:

问题在于这样的函数:

public void problemFunction (Object o) {
  if ( o instanceof Foo && o instanceof Bar) {
      doSomething((Problematic cast) o);
  }
}

}

4

5 回答 5

26

Java 8 引入了使用附加边界进行强制转换的可能性。您可以将 a Objectas a classwith multiple interfaces(或仅 as multiple interfaces)。

所以这:

doSomething((Problematic cast) o);

简单地变成这样:

doSomething((Foo & Bar) o);
于 2015-10-09T23:59:32.327 回答
13

不幸的是,没有可以满足这种情况的合法演员。必须有一个已知的类型来实现您需要作为边界的所有接口,以便您可以强制转换为它。可能是您为此目的创建的类型,也可能是某些现有类型。

interface Baz extends Foo, Bar { }

public void caller(Object w) {
  doSomething((Baz) w);
}

如果已知其他类型(例如Baz,以满足界限),则可以测试这些类型,并在调用者中使用一个分支来调用doSomething这些类型的强制转换。这不漂亮。

您还可以使用委托,创建您自己的Baz符合doSomething. 然后将传递的对象包装在Baz类的实例中,并将该包装器传递给doSomething.

private static class FooBarAdapter implements Foo, Bar {
  private final Object adaptee;
  FooBarAdapter(Object o) {
    adaptee = (Foo) (Bar) o;
  }
  public int flip() { return ((Foo) adaptee).flip(); }
  public void flop(int x) { ((Foo) adaptee).flop(x); }
  public void blort() { ((Bar) adaptee).blort(); }
}

public void problemFunction (Object o) {
  doSomething(new FooBarAdapter(o));
}
于 2008-11-25T18:06:54.837 回答
7
public static <T extends Foo & Bar> void doSomething(T object)

这似乎表明您将对相关对象执行多个操作。

我会争辩说,如果您对对象执行的所需操作足够不同,可以跨接口分离,那么它们就足够不同,值得拥有自己的方法。

您很可能可以重组此代码以调用单独的方法来执行所需的操作。从客户的角度来看,这最终可能会使整个操作更加清晰。

代替:

public void problemFunction (Object o) {
  if (o instanceof Foo && o instanceof Bar) {
      doSomething((Problematic cast) o);
  }
}

它成为了:

public void problemFunction(Object o) {
  if (o instanceof Foo && o instanceof Bar) {
      fooifySomething((Foo) o);
      baratizeSomething((Bar) o);
  }
}
于 2008-11-25T20:27:40.403 回答
6

通过将联合类型编码为方法的类型参数的可怕方式,可以“向上转换”为联合类型;对于您的示例,您可以编写

private <Q extends Foo & Bar> Q upcast(final Object in) {
    return (Q) in;
}

// ... elsewhere...

if (myObject instanceof Foo && myObject instanceof Bar) {
    doSomething(upcast(myObject));
}
于 2014-12-02T16:25:14.063 回答
-1

作为一种解决方法,您可以定义另一个接口 FooBar 扩展 Foo 和 Bar 并让您的类实现它。它甚至不必是顶级接口 - 如果您不想弄乱或改进其余代码,则可以将其声明为私有:

private interface FooBar extends Foo, Bar {}
public void problemFunction (Object o) {
  if ( o instanceof Foo && o instanceof Bar) {
      doSomething((FooBar) o);
  }
}
于 2008-11-25T18:18:39.727 回答