Mangos
Mangos

Reputation: 147

How to use class type of method parameter?

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

Answers (4)

Polygnome
Polygnome

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

Linitha
Linitha

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

pirho
pirho

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

a guest
a guest

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

Related Questions