简体   繁体   中英

How to Dynamically call a method of a class if class name is passed as string

I want to create dynamic object so that I call the respective method of the class. All classes and interface is in different file but under the same folder Given:

interface Method
{
    public void display();
}
class Car implements Method
{
     public void display()
     {
       System.out.print("Car method");
     }
}
class Honda implements Method
{
     public void display()
     {
       System.out.print("Honda method");
     }
}

public class Main {

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    String className = "Car";
    Class cls = Class.forName(className);
    Method method = (Method) cls.getConstructor().newInstance();
    method.display();
  }
}

Now if pass Honda in the string then I want to string method to get called but if I pass Car in string then I want to get Car method as an output but after compilation this method is not getting called. There is no error but no expected output as well. How to get the desired output. Please help.

You can invoke the desired method.

Method method = cls.getMethod("display");
method.invoke(parameters);

If I am allowed to update above code, it would be something like below,

interface Car
{
    public void display();
}
class Honda implements Car
{
     public void display()
     {
       System.out.print("Car method");
     }
}

public class Main {

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    String className = "Car";
    Class cls = Class.forName(className);
    Honda honda = (Honda)cls.newInstance()
    honda.display();
}
}

Hopefully this will clear the things about the Method class I mentioned in above answer.

The method class.newInstance() has been deprecated. So you should use

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class).newInstance();
Object object = ctor.newInstance(ctorArgument);

SN: In this case I assumed the constructor had only one String parameter value. the getConstructor method must be called passing all the class types (correctly ordered) that the desired constructor has. While with newInstance you need to pass the actual constrctor's args' values

At this point you have to get the method with getMethod() which requires both the method name and all the arguments' types. To actually invoke the method, you pass the instance of the object of which to call the method (in this case our object and passing the actual parameters' values to call it with

clazz.getMethod("methodName", String.class, String.class).invoke(object, "parameter1", "parameter2");

EDIT : The OP updated the question implementing a common interface by both classes. In this case you can actually call the method that you KNOW will have every class implementing that interface. This way you don't have to use any reflections magic except for creating the new instance of the object itself

With the common interface it'd be

Method method = (Method) Class.forName(className).getConstructor().newInstance();
method.display();

The last line will call the display method of the object instance that is implementing the interface

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM