Reputation: 147
I have the following classes: Foo1 extends Bar and Foo2 extends Bar
I would like to pass the type of either Foo1, or Foo2 in my method to create either a Foo1, or a Foo2, like this:
public Bar createMethod( "either type of Foo1, or Foo2" fooType) {
//returns the foo1 or foo2
}
Is there any approach to achieve this?
Upvotes: 0
Views: 113
Reputation: 7795
Java does not have union types, so a type like A | B
is not possible in Java.
Java 15 saw the addition of sealed types via JEP 360, so you can create a sealed type hierarchy with only two types that cannot be extended, effectively simulating union types for your own types.
By passing an instance of Class
, you can then use reflection to instantiate the type.
public sealed interface FooBar permits Foo, Bar { }
public final class Bar implements FooBar { }
public final class Foo implements FooBar { }
public FooBar createMethod(Class<? extends FooBar> type) {
return type.newInstance();
}
Without sealed types, you have to live with the fact that 3rd parties might extend your types, thus making more than just the two types possible as parameters for the method.
Another possibility is using Strings, and using Class.forName(String)
to get the type associated with the fully qualified class:
public FooBar createMethod(String type) {
if (type.equals("your.type.Foo") || type.equals("your.type.Bar"))
return Class.forName(type).newInstance();
}
Upvotes: 0
Reputation: 153
Here is the code:
public static void main(String args[]){
Bar barB = createMethod(FooB.class);
Bar barA = createMethod(FooA.class);
System.out.println("barB is instance of B " + (barB instanceof FooB) );
System.out.println("barA is instance of A " + (barA instanceof FooA) );
}
public static Bar createMethod(Class foo) {
if(foo.equals(FooA.class)) {
FooA fooA = new FooA();
return (Bar) fooA;
}
else{
FooB fooB = new FooB();
return (Bar) fooB;
}
}
}
class Bar{}
class FooA extends Bar{}
class FooB extends Bar{}
And your FooA and FooB extend Bar.
Upvotes: 1
Reputation: 12205
You can have some flexibility using generics, by declaring:
public <T extends Bar> T createMethod(Class<T> foo) {
// do the factoring
retrun (T) foo1 // (or foo2 depending on the foo passed);
}
With this all the following assignmennts are valid:
Bar b1 = createMethod(Foo1.class);
Bar b2 = createMethod(Foo2.class);
Foo1 f1 = createMethod(Foo1.class);
Foo2 f2 = createMethod(Foo2.class);
Note: at runtime you will get a ClassCastException
if you do not return the expected type. So if you fore example do this:
public <T extends Bar> T createMethod(Class<T> foo) {
return (T)new Foo2();
}
and
Foo1 foo1 = createMethod(Foo1.class);
Upvotes: 1
Reputation: 472
You can declare
public Bar createMethod(Class<? extends Bar> fooType) {
//returns the foo1 or foo2
}
and then call as in
Bar bar = createMethod(Foo1.class);
Upvotes: -1