0

I have a problem. In my code I have the following line:

HashMap<String, String> strategyResponse = strategy_005.run(runDateTimeLocal);

This function is inside the strategy_005 class:

public class strategy_005 {

    public static HashMap<String, String> run(Integer i) {

        HashMap<String, String> output = new HashMap<>();
        output.put("Response", i.toString());
        return output;

    }

}

I am not calling the function in the strategy_005 class, but in my MainClass. The problem I have is that the 005 part in the class is dynamic, so I have multiple classes from strategy_001 to strategy_015.

Here is the code from my MainClass:

public class MainClass {

    public static void main(String[] args) {

        for (int i = 1; i <= 15; i++) {
            
            // Call every "strategy_0(i)" run() method
            HashMap<String, String> strategyResponse = strategy_005.run(i);
            System.out.println(strategyResponse.get("Response"));

        }

    }

}

I know how to invoke methods from a class by name, but I don't know how to invoke a class and then call the method that I do know. The only thing I found that is close to what I want is this: Creating an instance using the class name and calling constructor

Unfortunatly this topic is about calling the constructor, but I want to call a custom method. Please let me know how I can achieve this!

A. Vreeswijk
  • 822
  • 1
  • 19
  • 57
  • 3
    If you want the methods to be dynamically dispatched, why make them static? Create an interface and have a list of 15 instances of different classes (or anonymous classes, or lambdas, or whatever) which implement that interface. – kaya3 May 04 '21 at 23:00
  • Does this do what you need? https://stackoverflow.com/questions/11594797/dynamically-load-a-class-and-invoke-a-method-in-java – Jerry Jeremiah May 04 '21 at 23:01
  • Yeah, but the 15 can be expanded. So I am looking for a solution where I don't have to add a new instance manually – A. Vreeswijk May 04 '21 at 23:01
  • 2
    How would adding an instance be harder than adding a class? – kaya3 May 04 '21 at 23:03
  • `clazz.getMethod` reflection method works the same way as `clazz.getConstructor` like in the post you found – OneCricketeer May 04 '21 at 23:06

2 Answers2

0

So what I would do is try making a Strategy abstract class, then making all 0 through 15 extend from Strategy. Then make a method in Strategy.java

public static HashMap<String, String> run( ? extends Strategy, Integer i ) {
    Strategy.getResponse() ...
}

? extends Strategy means any subclass of Strategy (in this case Strats 0-15) Then you would construct it in the main and call

Strategy.run( strategyResponse, i)

I tried doing what I said here and I can't get it to compile correctly. Instead I made a dummy class to play around with:

public class Strategies< T extends AbstractStrategy >
{
    ArrayList<? extends AbstractStrategy> li = new ArrayList<>() ;
    
    public HashMap<String,String> run( Strategies<?> strat ) 
    {
        HashMap<String,String> map = new HashMap<>() ;
        return map ;
    }
    
}

both of those compile so you might be able to play around with the syntax a bit to get it to your liking and usage.

  • Your initial suggestion won't work for static methods. You need an instance of the class in order to dispatch to the correct implementation. – something May 04 '21 at 23:56
0

you can invoke methods using reflection:

public HashMap<String, String> invoke(int i, int arg0){
    Class<?> clz = Class.forName("package_name.strategy_" + i);
    Method method = clz.getDeclaredMethod("run", int.class);
    return (HashMap<String, String>) method.invoke(null, arg0);
}

for(int i = 0; i < 15; i++){
    HashMap<String, String> output = invoke(i, runDateTimeLocal);
}

the name of class for Class.forName("package_name.strategy_" + i); must be fully quallified with package name

user3840019
  • 155
  • 1
  • 10