javanosuchmethoderrorgetmethod

Java getMethod(), NoSuchMethodException though method exists


I am trying to code a method 'interaction' which takes a keyboard input and calls the respective function. However, I am getting NoSuchMethodExceptions even when the input is valid.

public class Battle {
  public void interaction (String input, int x, int y, int z, Unit target) {
    Mechanic mch = new Mechanic();
    try {
      Method method = mch.getClass().getMethod(input, empty.getClass(), int.class, int.class, int.class, target.getClass());
      method.invoke(mch, empty,x, y, z, target);
  
    } catch (Exception ex) {
      System.out.print(ex.getClass().toString());
    }
  }

  private Dice[] empty = {};
}

public class Mechanic {
  public void fight (Dice[] dices, int x, int y, int z, Unit target) {
    int a = 0; // Some method involving dices in the actual code.
    Unit.setHp(x - y - z - a);
  }

  public void buff (int x, int y, int z, Unit target) {
    int a = 0; // Some method involving dices in the actual code.
    Unit.setAttack(x + y + z + a);
  }

// A class called Dice.
}

I do not understand why getMethod() is unable to find the methods 'fight' or 'buff' from class Mechanic.

I expect to be able to call the methods via a string input (and the corresponding arguments, but it just does not work. What am I doing wrong?


Solution

  • As a general rule, you should avoid doing what you're doing. Runtime reflection is a minefield of bugs waiting to happen. Don't do this to yourself. Find a way to implement this behavior with proper OOP design.

    I don't have enough information to say for sure, but the type parameters you used are a red flag to me.

    getMethod(input, empty.getClass(), int.class, int.class, int.class, target.getClass())
    

    Using the class of instances is dangerous since getMethod looks for an exact type match. For if empty or target are subclasses of the types in your actual method parameter list, you're not going to find the method you want. You should try, as much as possible, to explicitly provide the exact class of your parameter list. Something like:

    getMethod(input, MyEmptyClass.class, int.class, int.class, int.class, MyTargetClass.class)