2

I am trying to invoke a method using reflection.

The method I am invoking is not static and in the same class I am invoking it from.

A simplified version of my code:

public class Test {
  public static void main(String[] args) {
    Test instance = new Test();
    if (args.length > 0) {
      instance.doWork(args[0]);
    }
  }

  private void doWork(String methodName) {
    Method method;

    try {
      method = this.getClass().getMethod(methodName);
      method.invoke(this);
    } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
      [...]
    }
  }

  private void MethodOne() { ... };
  private void MethodTwo() { ... };
  [...]
  private void MethodTwenty() { ... };
}

What I am getting is a java.lang.NoSuchMethodException: correct.package.and.class.MethodTwo() despite the package / class / method existing.

Can someone tell me what I am doing wrong?

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
Jdv
  • 962
  • 10
  • 34

3 Answers3

2

What I am getting is a java.lang.NoSuchMethodException: correct.package.and.class.MethodTwo()...

you are calling the getMethod() which is not giving back the private method

Assuming that arg[0] has the right name of the method (if not you'll get a java.lang.NoSuchMethodException again), 2 thing must be done here:

  1. you need to use getDeclaredMethod (because MethodOne is private declared)

  2. your need to set the flag for access to it .setAccessible(true) (this will allow you to invoke a method that is declared private)

Example:

    Method method;
    try {
        method = f.getClass().getDeclaredMethod("doThis");

        method.setAccessible(true);
        method.invoke(f);
    } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
            | InvocationTargetException e) {
        System.err.println("Opala, somethign went wrong here!");
    } 
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
0

The way you are accessing method is correct. The method access specifier is private. Thus it is throwing error.

Please change the access specifier to public, it will work.

import java.lang.reflect.Method;

public class Test {
  public static void main(String[] args) {
    Test instance = new Test();
    if (args.length > 0) {
      instance.doWork(args[0]);
    }
  }

  private void doWork(String methodName) {
    Method method;

    try {
      method = this.getClass().getMethod(methodName);
      method.invoke(this);
    } catch (Exception e) {

    }
  }

  public void MethodOne() { System.out.println("Method 1"); };
  public void MethodTwo() { System.out.println("Method 2"); };
  public void MethodTwenty() { System.out.println("Method 3"); };
}

If you are trying to access private methods or constructors, you need to change the code.

Thanks, Thiruppathi S

Govind Raj
  • 105
  • 6
  • I also tried this way and it works great. I've went with the accepted answer as it didn't force me to set the methods to public though. – Jdv Apr 12 '17 at 10:57
0

CLASS TO INVOKE METHODS FROM

public class Computer {

private String brandName;
private int yearManufactured;

public String getBrandName() {
    return brandName;
 }

public void setBrandName(String brandName) {
    this.brandName = brandName;
 }

public int getYearManufactured() {
    return yearManufactured;
 }

public void setYearManufactured(int yearManufactured) {
    this.yearManufactured = yearManufactured;
 }

}

IMPLEMENTATION CLASS

public class Test {

public static void main(String[] args) throws NoSuchMethodException,  
        InvocationTargetException, IllegalAccessException{
          
    Class curClass = Computer.class;
    Method[] allMethods = curClass.getDeclaredMethods();
    
    Computer myComputer = new Computer();
          
    for(int c = 0; c < allMethods.length; c++){
             
        Class[] parameterTypes = allMethods[c].getParameterTypes();           
        for(Class parameterType: parameterTypes){
           
           System.out.println(parameterType.getName());                
           
           switch(parameterType.getName()){
           
               case "java.lang.String":                     
                   allMethods[c].invoke(myComputer, "LENOVO");
               break;
               
               case "int":        
                   allMethods[c].invoke(myComputer, 2021);
               break;               
           }
        }                 
    }
    
    System.out.println("BRAND NAME :"+myComputer.getBrandName());
    System.out.println("YEAR MANUFACTURED: "+myComputer.getYearManufactured());

  }
 }
RynohRR
  • 299
  • 5
  • 12
  • I'll just add, maybe I'm wrong here, that if the method is static, you may omit 'myComputer' in invoke. – Wrapper Nov 15 '21 at 10:03