How should I cast for Java generic with multiple bounds?

12,219

Solution 1

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

So this:

doSomething((Problematic cast) o);

simply becomes to this:

doSomething((Foo & Bar) o);

Solution 2

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 doSomething with a cast to those types. It's not pretty.

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

Solution 3

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

Solution 4

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));
}
Share:
12,219
user1535501
Author by

user1535501

programmer at Basenet Internet services.

Updated on June 05, 2022

Comments

  • user1535501
    user1535501 almost 2 years

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

    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).

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

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

    }

  • Sled
    Sled almost 13 years
    I believe this won't work since there is no guarantee the o actually has "implements FooBar". I don't think Java will just assume it.
  • AlikElzin-kilaka
    AlikElzin-kilaka over 12 years
    Good idea. I used it in a slightly different way. I prefer the FooBarAdapter to get to objects with the 2 different types. The == can be used to check if it's the same object (no a must). This way, their is a compile time type check.
  • Dandre Allison
    Dandre Allison about 11 years
    I combined this delegated pattern anonymous/named inner method classes to "cast" an object I know to extend/implement a set of classes and interfaces to meant the bound requirements. See Jon's answer: stackoverflow.com/a/9514406/910718
  • Goodwine
    Goodwine about 11 years
    LMAO fooify, that's new to me xD
  • Jiří Vypědřík
    Jiří Vypědřík over 9 years
    And this seems to be the limitation of the Java language because in Scala running on the same JVM, this is easy as o.asInstanceOf[Foo with Bar]
  • cquezel
    cquezel about 9 years
    @ArtB The answer says "and have your class implement that.".
  • William Jarvis
    William Jarvis over 7 years
    Thanks. Only annoyance is it generates an unchecked cast. However I used a modified version which takes Foo rather than Object and checks it implements Bar and then returns with the cast as you have done otherwise throwing a ClassCastException.