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..
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
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
Related
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?
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:
you need to use getDeclaredMethod (because MethodOne is private declared)
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!");
}
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
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());
}
}
I am trying to run a class from another class. But it asks me to change the type when I store the class name in an array. I want the user to enter a number which would be fed into the array and run the class at that array value.
Here is my code so far:
public class All_Challenges {
public static void main(String[] args) {
System.out.println("Which class do you want to run?: ");
System.out.println("1. The first class");
Class[] theFiles = new Class[31];
theFiles[1] = Challenge_1_Whats_Your_Name.main(args);
theFiles[1].main(args);
}
}
The last two lines are giving me an error because they are making me change the class type from The void to type class and then making add a return statement. I have around 30 of these so I would prefer not to have to change my main method in all my other classes. What stuff should I write so that I don't have to do this. I think it's something to do with what "type" my array is. Or maybe it's to do with the line main.(args);
Weird part is that it doesn't ask me to change the type when I don't call it from an array.
The problem is that you are trying to put a method to array of classes.
Class[] theFiles = new Class[31];
theFiles[1] = Challenge_1_Whats_Your_Name.class;
try {
theFiles[1].getMethod("main", String[].class).invoke(args);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
That should work for you
You can do it using reflections:
public class TestMain {
private static final Class<?>[] classArray = {A.class, B.class};
public static void main(String[] args) {
for (Class<?> classExec : classArray) {
try {
//get main
Method method = classExec.getMethod("main", String[].class);
method.invoke(null, (Object) args);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
public static class A {
public static void main(String[] args) {
System.out.println("A");
}
}
public static class B {
public static void main(String[] args) {
System.out.println("B");
}
}
}
Reference: https://stackoverflow.com/a/4980149/1255493
I have a requirement where in i need to invoke method from class in a particular pattern which is obtained as input argument.
public RandomMethod(String ClassName){
//Eg For Class Name Abc , there is a method AbcProcessor which i need to invoke
ClassName.ClassNameProcessor
}
Since i am getting the argument as String , i am not able to figure out how to cast String into a form where i can call something like Abc.AbcProcessor()
I believe there is some way to do this using reflections. But i am not sure how to proceed.
By reflection you can do that, try following sample:
Class A:
public class A {
public void print(){
System.out.println("A");
}
}
Class B:
public class B {
public void print(){
System.out.println("B");
}
}
Invoking print() from A and B:
public class Test {
public static void callPrint(String className){
try {
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
clazz.getDeclaredMethod("print").invoke(obj);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
callPrint("test.A");
callPrint("test.B");
}
}
You need to use reflecton, indeed:
public void randomMethod(String fullyQualifiedClassName, String methodName) throws ReflectiveOperationException {
Class<?> clazz = Class.forName(fullyQualifiedClassName);
clazz.getMethod(methodName).invoke(null);
}
which would work assuming you are calling public static method with no arguments
I am attempting to call a custom class and method on my Application start-up to perform dev testing. I have stored the setting for my test class and method in my SettingsClass as shown below.
public class SettingsClass {
public static final boolean BOOT_TEST = true;
public static final String BOOT_CLASS = "MyClass";
public static final String BOOT_METHOD = "MyMethod";
}
My Main Class.
public class MainClass {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
if(SettingsClass.BOOT_TEST) {
Method method = getDeclaredMethodClass(SettingsClass.BOOT_CLASS).getDeclaredMethod(SettingsClass.BOOT_METHOD);
method.invoke();
System.exit(1);
}
}
Is it possible to perform the above action?
Any help would be appreciated.
You need both a reference to the Class type and an instance of the class (unless the method you want to invoke is static). In your pseudo code you have the correct idea, all you need to do is a quick review of the javadoc for java.lang.Class and java.lang.reflect.Method
public class SettingsClass {
public static final boolean BOOT_TEST = true;
public static final String BOOT_CLASS = "MyClass";
public static final String BOOT_METHOD = "doMain";
}
public class MyClass {
public static void doMain() {
}
}
public class MainClass {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
if(SettingsClass.BOOT_TEST) {
Class<?> clazz = Class.forName(SettingsClass.BOOT_CLASS);
Method m = clazz.getMethod(SettingsClass.BOOT_METHOD);
m.invoke(null);
System.exit(1);
}
}
for .invoke() you need an object that is an instance of your class.
if your class has an public default consturctor you should be able to do something like this
// load your class
Class<?> clazz = Class.forName("full.package.and.class.name");
// get the method
Method method = clazz.getDeclaredMethod("methodName");
// create an instance of your class
Object object = clazz.newInstance();
// call the method in context of object
method.invoke(object);
You can refer to Java reflection (Method Invocation)
http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html
you can find methods through
Class<?> c = Class.forName("nameClass");
Object t = c.newInstance();
Method[] allMethods = c.getDeclaredMethods();
and you can call through
m.setAccessible(true);
Object o = m.invoke(t, .... )
Yes, it is. The following code will execute the method someMethod in the MainClass.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MainClass {
public static final boolean BOOT_TEST = true;
public static final String BOOT_CLASS = "MainClass";
public static final String BOOT_METHOD = "someMethod";
public static void main(String[] args) throws InstantiationException,
IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
if (MainClass.BOOT_TEST) {
Class bootClass = Class.forName(BOOT_CLASS);
Method bootMethod = bootClass.getDeclaredMethod(BOOT_METHOD, null);
bootMethod.invoke(null, null);
}
}
public static void someMethod() {
System.out.println("Some method executing...");
}
}
What you need to do is get the class object for the class whose method you wish to execute dynamically by using the static method Class.forName(String) passing in the class's name. subsequently you can request the method you wish to execute using the getDeclaredMethod(String, Class<?>...) passing in the method's name and parameter types. Following that you can call invoke(Object, Object...) on the method with two null arguments (execute the method on no instance of the class (static execution) without any parameters).
I want do something like this :
public myMethod(Object expectedValue) {
java.lang.reflect.Method method = new Method(expectedValue);
System.out.println(method.getName());
}
How do I get a method reference from the getter itself without introducing string coupling (specifying the getter name) ?
Don't know if I understood your question right, but below you'll find the code who you can invoke a getter from an object using reflection. Afaik, there is no way to get a method without refering to its name.
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Foo foo = new Foo();
foo.setBla("i am bla");
Method blaGetter = Foo.class.getMethod("getBla");
System.err.println(blaGetter.invoke(foo));
}
private static class Foo {
private String bla;
public String getBla() {
return bla;
}
public void setBla(String bla) {
this.bla = bla;
}
}