我应该如何为具有多个边界的 Java 泛型进行转换?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/318208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:55:44  来源:igfitidea点击:

How should I cast for Java generic with multiple bounds?

javagenericscastingpolymorphism

提问by pvgoddijn

Is it possible to cast an object in Java to a combined generic type?

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

I have a method like:

我有一个方法,如:

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

Calling this method is no problem if I have a class that implements both interfaces (Foo & Bar).

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

The problem is when I need to call this method the object I need to pass to it is received as java.lang.Objectand I need to cast it to make the compiler happy. But I can't figure out how to make this cast.

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

edit:

编辑:

The problem lies in a function like this:

问题在于这样的函数:

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

}

}

采纳答案by erickson

Unfortunately, there is no legal cast that you can make to satisfy this situation. There must be a single type known to implement all of the interfaces that you need as bounds, so that you can cast to it. The might be a type you create for the purpose, or some existing type.

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

interface Baz extends Foo, Bar { }

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

If other types are known, like Baz, to meet the bounds, you could test for those types, and have a branch in your caller that calls doSomethingwith a cast to those types. It's not pretty.

如果其他类型是已知的,例如Baz,以满足边界,您可以测试这些类型,并在您的调用者中有一个分支,调用doSomething这些类型的强制转换。它不漂亮。

You could also use delegation, creating your own class Bazthat meets the bounds required by doSomething. Then wrap the object you are passed in an instance of your Bazclass, and pass that wrapper to 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));
}

回答by Ron C

Java 8 introduces the possibility of casting with additional bounds. You can cast an Objectas a classwith multiple interfaces(or just as multiple interfaces).

Java 8 引入了使用附加边界进行强制转换的可能性。您可以将 an Objectas aclass与多个interfaces(或仅作为 multiple interfaces)进行转换。

So this:

所以这:

doSomething((Problematic cast) o);

simply becomes to this:

简单地变成这样:

doSomething((Foo & Bar) o);

回答by James Van Huis

public static <T extends Foo & Bar> void doSomething(T object)

This seems to denote that you would be performing more than one operation on the object in question.

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

I would argue that if the desired operations you are performing on the object are distinct enough to be seperated across interfaces, then they are distinct enough to deserve their own methods.

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

It is likely that you could restructure this code to call seperate methods to perform the desired operation. This may end up making the entire operation more clear from the client's perspective.

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

Instead of:

代替:

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

It becomes:

它成为了:

public void problemFunction(Object o) {
  if (o instanceof Foo && o instanceof Bar) {
      fooifySomething((Foo) o);
      baratizeSomething((Bar) o);
  }
}

回答by user4316588

It is possible to "up-cast" to a union type, by the horrible means of encoding the union type into a method's type parameter; for your example you can write

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

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

// ... elsewhere...

if (myObject instanceof Foo && myObject instanceof Bar) {
    doSomething(upcast(myObject));
}

回答by sk.

As a workaround, you could define another interface FooBar that extends Foo and Bar and have your class implement that. It doesn't even have to be a top-level interface - you can declare it private if you don't want to clutter up or retrofit the rest of your code:

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

private interface FooBar extends Foo, Bar {}
public void problemFunction (Object o) {
  if ( o instanceof Foo && o instanceof Bar) {
      doSomething((FooBar) o);
  }
}