Is it possible to cast an object in Java to a combined generic type?
I have a method like:
public static void doSomet
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);
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:
private interface FooBar extends Foo, Bar {}
public void problemFunction (Object o) {
if ( o instanceof Foo && o instanceof Bar) {
doSomething((FooBar) o);
}
}
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));
}
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));
}
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);
}
}