Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically calling a class method in java?

Tags:

java

Is it possible to dynamically call a method on a class from java?

E.g, lets say I have the reference to a class, e.g either the string: 'com.foo.Bar', or com.foo.Bar.class, or anything else which is needed..). And I have an array / list of strings, e.g [First, Last, Email].

I want to simply loop through this array, and call the method 'validate' + element on the class that I have a reference to. E.g:

MyInterface item = //instantiate the com.foo.Bar class here somehow, I'm not sure how.

item.validateFirst();
item.validateLast();
item.validateEmail();

I want the above lines of code to happen dynamically, so I can change the reference to a different class, and the names in my string list can change, but it will still call the validate + name method on whichever class it has the reference to.

Is that possible?

like image 416
Ali Avatar asked Dec 05 '22 09:12

Ali


1 Answers

The simplest approach would be to use reflection

Given...

package com.foo;

public class Bar {

    public void validateFirst() {
        System.out.println("validateFirst");
    }

    public void validateLast() {
        System.out.println("validateLast");
    }

    public void validateEmail() {
        System.out.println("validateEmail");
    }

}

You could use something like...

String methodNames[] = new String[]{"First", "Last", "Email"};
String className = "com.foo.Bar";
try {

    Class classRef = Class.forName(className);
    Object instance = classRef.newInstance();

    for (String methodName : methodNames) {

        try {

            Method method = classRef.getDeclaredMethod("validate" + methodName);
            method.invoke(instance);

        } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
            ex.printStackTrace();
        }

    }

} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
    ex.printStackTrace();
}

To look up the methods and execute them.

You will need to decide the best way to handle errors and what they mean to you, but it wouldn't be a difficult them to expand the idea to a reusable method...

Updated with idea of concept discussed in comments

Given....

public interface Validator {
    public boolean isValid(Properties formProperties);
}

We can create one or more...

public class UserRegistrationValidator implements Validator {
    public boolean isValid(Properties formProperties) {
        boolean isValid = false;
        // Required fields...
        if (formProperties.containsKey("firstName") && formProperties.containsKey("lastName") && formProperties.containsKey("email")) {
            // Further processing, valid each required field...
        }
        if (isValid) {
            // Process optional parameters
        }
        return isValid;
    }
}

Then from our input controller, we can look and valid the required forms

public class FormController ... {

    private Map<String, Validator> validators;

    public void validForm(String formName, Properties formProperties) {
        boolean isValid = false;
        Validator validator = validators.get(formName);
        if (validator != null) {
            isValid = validate.isValid(formProperties);
        }
        return isValid;
    }

}

Of course you need to provide some way to register the Validators and there may be differences based on the backbone framework you are using and the parameters you can use (you don't have to use Properties, but it is basically just a Map<String, String>...)

like image 115
MadProgrammer Avatar answered Dec 23 '22 21:12

MadProgrammer