-2

I'm testing with Java reflection and trying to apply overloaded method to parameters according to their type..

However, I have NoSuchMethodException even though the method I tried to get is public. This exception still appears when I used getDeclaredMethod.

Here's the main program

public class Test {

    public static void main(Object... inputs){

        InputManipulation test = new InputManipulation();

        for (Object input: inputs){
            Class ownerClass = test.getClass();
            Class inputClass = input.getClass();
            Method method = ownerClass.getDeclaredMethod("add", inputClass);
            method.invoke(test, "Testing reflection");
        }

    }
}

And here's the self-defined InputManipulation class

public class InputManipulation {

    Integer total;

    public InputManipulation(){this.total = 0;}

    public void add(Integer num){this.total += num;}
    public void add(String str){System.out.println(str);}
}

Thanks in advance!

I now changed the Test class as follows.. but the problem still exists.

public class Test {

    public static void main(String[] args){
        Test testExample = new Test();
        testExample.testMethod("String1", 1, "String2");
    }

    public void testMethod(Object... inputs){
        InputManipulation test = new InputManipulation();
        for (Object input: inputs){
            Class ownerClass = test.getClass();
            Class inputClass = input.getClass();
            Method method = ownerClass.getDeclaredMethod("add", inputClass);
            method.invoke(test, "Testing reflection");
        }

    }
}

I also tried putting the inputClass into an array of Class, as suggested by another post, but it didn't help..

Cheryl
  • 39
  • 8
  • How do you start this application ? – Rafał Sokalski Jun 08 '18 at 12:17
  • What is the argument that you are passing to class Test ? – soufrk Jun 08 '18 at 12:19
  • @RafałSokalski I didn't actually write anything to start the application.. But IntelliJ is giving me this exception message. – Cheryl Jun 08 '18 at 12:19
  • You need to add `throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException` to `main method` – XtremeBaumer Jun 08 '18 at 12:21
  • 1
    Your `main()` method does not have the Java proper `main()` method signature, look here https://www.protechtraining.com/content/java_fundamentals_tutorial-hello_world – Honza Zidek Jun 08 '18 at 12:22
  • @MaxVollmer The OP has already *answered* your question: "I didn't actually write anything to start the application" :) – Honza Zidek Jun 08 '18 at 12:24
  • 1
    Your code is **not compilable**, how can you even get an exception?! – Honza Zidek Jun 08 '18 at 12:25
  • 1
    OP actually talks about the compiler error: `Unhandled exception type NoSuchMethodException` – XtremeBaumer Jun 08 '18 at 12:26
  • @XtremeBaumer Yes! I'm sorry but I'm not very familiar with Java, so I wasn't clear enough in the first place.. – Cheryl Jun 08 '18 at 12:29
  • 2
    @CherylYang have a look at my first comment for the fix. Actually if you have a proper IDE, it should suggest you how to fix it – XtremeBaumer Jun 08 '18 at 12:30
  • @XtremeBaumer I tried.. It didn't work :( – Cheryl Jun 08 '18 at 12:32
  • @CherylYang Please read the XtremeBaumer's comment more carefully and do what he advises. Please start here: https://docs.oracle.com/javase/tutorial/essential/exceptions/ – Honza Zidek Jun 08 '18 at 12:32
  • `method.invoke(test, "Testing reflection");` should be changed to `method.invoke(test, input);` because you want to invoke the methods on the arguments you pass and not on the string. You get an error because you pass an string to the `add(Integer num)` method which causes the exception – XtremeBaumer Jun 08 '18 at 12:36
  • @HonzaZidek I put throws exceptions to both main and testMethod so that it can work. Then when I run it, it says java.lang.IllegalArgumentException: argument type mismatch at method.invoke line. I'm more confused... Sorry for all the trouble figuring out the problem.. – Cheryl Jun 08 '18 at 12:38
  • @XtremeBaumer Thank you! This fixed the problem. I'm still a bit confused at why putting throws exceptions line for both methods, but I will look more into exception part! – Cheryl Jun 08 '18 at 12:39
  • You always pass the **String** `"Testing reflection"` to the add method, but on the second iteration it expects an **Integer** – XtremeBaumer Jun 08 '18 at 12:39
  • Did one of these answers not work for you? – ViaTech Jun 09 '18 at 17:02

2 Answers2

0
public class Test {

public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    Test testExample = new Test();
    testExample.testMethod("String1", 1, "String2");
}

public void testMethod(Object... inputs) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    InputManipulation test = new InputManipulation();
    for (Object input: inputs){
        Class ownerClass = test.getClass();
        Class inputClass = input.getClass();
        Method method = ownerClass.getDeclaredMethod("add", inputClass);
        method.invoke(test, input);
    }
}
}

Your problem was caused by this method.invoke(test, "Testing reflection"); You iterate through 2 types of arguments and depends of this argument you invoke method 'add'. When you tried to invoke method with argument Integer you pass to method String parameter that causes error

Rafał Sokalski
  • 1,817
  • 2
  • 17
  • 29
0

There seems to be a few issues with the initial code you provided and as others have suggested using an IDE would have pointed some of the issues out pretty quickly. However, I have taken your update and fixed the code to call the proper method in the loop you provided of input types.

First change your InputManipulation class like so:

public class InputManipulation {

    Integer total;

    public InputManipulation() {
        this.total = 0;
    }

    public void add(Integer num) {
        this.total += num;
        System.out.println(this.total);
    }

    public void add(String str) {
        System.out.println(str);
    }

}

Now alter your Test class like so:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) {
         Test testExample = new Test();
            testExample.testMethod("String1", 1, "String2");
    }

     public void testMethod(Object... inputs){
            InputManipulation test = new InputManipulation();
            for (Object input: inputs){

                Class<? extends Object> ownerClass = test.getClass();
                Class<? extends Object> inputClass = input.getClass();
                //Method method;    //not needed

                try {
                    ownerClass.getDeclaredMethod("add", inputClass).invoke(test, input);

                } catch (NoSuchMethodException | SecurityException | 
                        IllegalAccessException | IllegalArgumentException |
                        InvocationTargetException e) {

                    e.printStackTrace();
                }

            }

      }
}

I used these readings to help guide my answer, but altered the way I invoked the method:

http://tutorials.jenkov.com/java-reflection/methods.html

ViaTech
  • 2,143
  • 1
  • 16
  • 51