Jak wywołać metodę Java po podaniu nazwy metody jako ciągu?

684

Jeśli mam dwie zmienne:

Object obj;
String methodName = "getName";

Nie znając klasy obj, jak mogę wywołać metodę identyfikowaną przez methodNamenią?

Wywoływana metoda nie ma parametrów i Stringzwraca wartość. To jest getter dla fasoli Java .

brasskazoo
źródło
3
Albo użyj interfejsu API odbicia, albo groovy
Peter Kelley,

Odpowiedzi:

972

Kodowanie z biodra wyglądałoby to tak:

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
  catch (NoSuchMethodException e) { ... }

Parametry określają bardzo konkretną metodę, której potrzebujesz (jeśli istnieje kilka przeciążonych dostępnych metod, jeśli metoda nie ma argumentów, podaj tylko methodName).

Następnie wywołujesz tę metodę, wywołując

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) { ... }
  catch (IllegalAccessException e) { ... }
  catch (InvocationTargetException e) { ... }

Ponownie pomiń argumenty .invoke, jeśli ich nie masz. Ale tak. Przeczytaj o Java Reflection

Henrik Paul
źródło
2
Byłem trochę zdenerwowany faktem, że Java używa usuwania typu, ale wiedząc, że przynajmniej ma Reflection poprawia mi nastrój: D A teraz z lambdami w Javie 8 język naprawdę zaczyna nadążać za nowoczesnym rozwojem. Jedyne, czego teraz brakuje, to natywne wsparcie dla programów pobierających i ustawiających lub właściwości znane w języku C #.
7hi4g0
120
To niesprawiedliwe -1. Henrik prawdopodobnie nie opowiada się za wyjątkami związanymi ze zgniataniem i nie napisał dla nich niczego, ponieważ stara się tylko zademonstrować refleksję.
zremisował
70
Plus jeden za pokazanie niektórych potencjalnych wyjątków. Gdybym to napisał, byłoby to ... catch (wyjątek e) {...
mikbanUtah
1
Dostałem „zmienna nie została zainicjowana” dla methodw method.invoke(obj, arg1, arg2,...);. A method = null;rozwiązuje problem, ale o tym wspomnieć w odpowiedzi nie jest złym pomysłem.
Amin
2
@ DeaMon1 Metody Java nie używają „kodów wyjścia”, ale jeśli metoda cokolwiek zwróci, zwróci wszystko, invokeco zwróciło. Jeśli wystąpi wyjątek prowadzenie sposobu, wyjątek nie zostanie owinięty w sposób InvocationTargetException.
ThePyroEagle,
194

Użyj wywołania metody z refleksji:

Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod("method name", parameterTypes);
method.invoke(objectToInvokeOn, params);

Gdzie:

  • "class name" to nazwa klasy
  • objectToInvokeOn jest typu Object i jest obiektem, na którym chcesz wywołać metodę
  • "method name" to nazwa metody, którą chcesz wywołać
  • parameterTypesjest typu Class[]i deklaruje parametry, które przyjmuje metoda
  • paramsjest typu Object[]i deklaruje parametry, które należy przekazać do metody
piekarnik
źródło
Fajnie, myślę, że masz rację z getDeclaredMethod (), to prawdopodobnie jest „bezpieczniejsze” niż getMethod () ..
brasskazoo
22
Źle. Tak, getDeclaredMethod działa z metodami prywatnymi i chronionymi. ALE: nie działa z metodami zdefiniowanymi w nadklasach (metody dziedziczone). Tak więc zależy to silnie od tego, co chcesz zrobić. W wielu przypadkach chcesz, aby działał niezależnie od dokładnej klasy, w której metoda jest zdefiniowana.
jrudolph
A gdzie mam umieścić plik „klasy”? najlepiej wyjaśnić dla Eclipse IDE
Dr.jacky
@ Mr.Hyde na ścieżce zajęć.
Stijn de Witt
Co powinienem wstawić do metody i method.invoke (), jeśli wywoływana metoda nie akceptuje żadnych parametrów? Wydaje się, że wciąż muszę podać drugi parametr, czy powinna to być pusta tablica obiektów?
Igor
101

Dla tych, którzy chcą prostego przykładu kodu w Javie 7:

Dog klasa:

package com.mypackage.bean;

public class Dog {
    private String name;
    private int age;

    public Dog() {
        // empty constructor
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void printDog(String name, int age) {
        System.out.println(name + " is " + age + " year(s) old.");
    }
}

ReflectionDemo klasa:

package com.mypackage.demo;

import java.lang.reflect.*;

public class ReflectionDemo {

    public static void main(String[] args) throws Exception {
        String dogClassName = "com.mypackage.bean.Dog";
        Class<?> dogClass = Class.forName(dogClassName); // convert string classname to class
        Object dog = dogClass.newInstance(); // invoke empty constructor

        String methodName = "";

        // with single parameter, return void
        methodName = "setName";
        Method setNameMethod = dog.getClass().getMethod(methodName, String.class);
        setNameMethod.invoke(dog, "Mishka"); // pass arg

        // without parameters, return string
        methodName = "getName";
        Method getNameMethod = dog.getClass().getMethod(methodName);
        String name = (String) getNameMethod.invoke(dog); // explicit cast

        // with multiple parameters
        methodName = "printDog";
        Class<?>[] paramTypes = {String.class, int.class};
        Method printDogMethod = dog.getClass().getMethod(methodName, paramTypes);
        printDogMethod.invoke(dog, name, 3); // pass args
    }
}

Wynik: Mishka is 3 year(s) old.


Możesz wywołać konstruktor z parametrami w ten sposób:

Constructor<?> dogConstructor = dogClass.getConstructor(String.class, int.class);
Object dog = dogConstructor.newInstance("Hachiko", 10);

Alternatywnie możesz usunąć

String dogClassName = "com.mypackage.bean.Dog";
Class<?> dogClass = Class.forName(dogClassName);
Object dog = dogClass.newInstance();

i robić

Dog dog = new Dog();

Method method = Dog.class.getMethod(methodName, ...);
method.invoke(dog, ...);

Sugerowana lektura: Tworzenie nowych wystąpień klasy

srebro
źródło
1
Najlepsza odpowiedź tutaj. Kompletne i zwięzłe
Reuben JaMes Aveño Gruta
1
Prawidłowa najlepsza odpowiedź.
Dhara Patel
Skąd masz Methodprzedmiot?
parlad
Od odbicia pkg.
srebrny
55

Metodę można wywołać w ten sposób. Jest też więcej możliwości (sprawdź API odbicia), ale ta jest najprostsza:

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

import org.junit.Assert;
import org.junit.Test;

public class ReflectionTest {

    private String methodName = "length";
    private String valueObject = "Some object";

    @Test
    public void testGetMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        Method m = valueObject.getClass().getMethod(methodName, new Class[] {});
        Object ret = m.invoke(valueObject, new Object[] {});
        Assert.assertEquals(11, ret);
    }



}
Petr Macek
źródło
7
+1 za jedyną odpowiedź, która uznała, że ​​OP określił „brak parametrów” w swoim pytaniu (i dlatego, że tego też szukałem).
John Fitzpatrick
16

Po pierwsze nie. Unikaj tego rodzaju kodu. Zazwyczaj jest to bardzo zły kod i niepewny (patrz sekcja 6 Wytycznych bezpiecznego kodowania dla języka programowania Java, wersja 2.0 ).

Jeśli musisz to zrobić, wolę java.beans od refleksji. Fasola otacza odbicie, umożliwiając względnie bezpieczny i konwencjonalny dostęp.

Tom Hawtin - tackline
źródło
11
Nie zgadzam się. Bardzo łatwo jest napisać taki kod, aby był bezpieczny i zrobiłem to w wielu językach. Na przykład można utworzyć zestaw dopuszczalnych metod i zezwolić na wywołanie metody tylko wtedy, gdy jej nazwa znajduje się w zestawie. Jeszcze bezpieczniejsze (ale wciąż proste) ograniczałoby każdą dozwoloną metodę do określonego stanu i nie pozwalało na wywołanie metody, chyba że wątek / interfejs / użytkownik / cokolwiek spełnia takie kryteria.
JSON,
Nigdy nie bądź tak kategoryczny wobec takich problemów. Obecnie tworzę prosty program, który pozwala użytkownikowi definiować dowolne zadania na dowolnych obiektach za pomocą interfejsów sieciowych. Wiem, że jest to rzeczywiście niepewne, ale odpowiednie testy są wykonywane po otrzymaniu konfiguracji, i pozwala programistom na łatwą konfigurację zadań, a także daje programom możliwość łączenia klas niestandardowych z kodem ogólnym (tzn. część, której używam do refleksji, aby umożliwić im konfigurację metod do użycia przez interfejs sieciowy) bez konieczności aktualizacji GUI.
DGoiko,
14

Aby uzupełnić odpowiedzi mojego kolegi, możesz zwrócić szczególną uwagę na:

  • wywołania statyczne lub instancji (w jednym przypadku nie potrzebujesz instancji klasy, w drugiej może być konieczne poleganie na istniejącym domyślnym konstruktorze, który może, ale nie musi)
  • publiczne lub niepubliczne wywołanie metody (w tym drugim przypadku należy wywołać metodę setAccessible w metodzie w bloku doPrivileged , inne błędy znalezienia nie będą zadowolone )
  • enkapsulując w jeszcze jeden wyjątek aplikacyjny, jeśli chcesz odrzucić liczne wyjątki systemu Java (stąd wyjątek CCEx w poniższym kodzie)

Oto stary kod java1.4, który uwzględnia te punkty:

/**
 * Allow for instance call, avoiding certain class circular dependencies. <br />
 * Calls even private method if java Security allows it.
 * @param aninstance instance on which method is invoked (if null, static call)
 * @param classname name of the class containing the method 
 * (can be null - ignored, actually - if instance if provided, must be provided if static call)
 * @param amethodname name of the method to invoke
 * @param parameterTypes array of Classes
 * @param parameters array of Object
 * @return resulting Object
 * @throws CCException if any problem
 */
public static Object reflectionCall(final Object aninstance, final String classname, final String amethodname, final Class[] parameterTypes, final Object[] parameters) throws CCException
{
    Object res;// = null;
    try {
        Class aclass;// = null;
        if(aninstance == null)
        {
            aclass = Class.forName(classname);
        }
        else
        {
            aclass = aninstance.getClass();
        }
        //Class[] parameterTypes = new Class[]{String[].class};
    final Method amethod = aclass.getDeclaredMethod(amethodname, parameterTypes);
        AccessController.doPrivileged(new PrivilegedAction() {
    public Object run() {
                amethod.setAccessible(true);
                return null; // nothing to return
            }
        });
        res = amethod.invoke(aninstance, parameters);
    } catch (final ClassNotFoundException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+CLASS, e);
    } catch (final SecurityException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_SECURITY_ISSUE, e);
    } catch (final NoSuchMethodException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_NOT_FOUND, e);
    } catch (final IllegalArgumentException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ILLEGAL_ARGUMENTS+String.valueOf(parameters)+GenericConstants.CLOSING_ROUND_BRACKET, e);
    } catch (final IllegalAccessException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ACCESS_RESTRICTION, e);
    } catch (final InvocationTargetException e) {
    throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_INVOCATION_ISSUE, e);
    } 
    return res;
}
VonC
źródło
12
Object obj;

Method method = obj.getClass().getMethod("methodName", null);

method.invoke(obj, null);
Ciastko Z Kurczaka
źródło
Obiekt powinien mieć co najmniej wartość / wartości.
Lova Chittumuri,
To działało naprawdę dobrze w stosunku do tego, czego potrzebowałem. Miałem klasę, która była już utworzona i po prostu potrzebowałem wyciągnąć z niej metodę. Dodawanie łap dla wyjątków jest tutaj dobrym pomysłem, ale poza tym działało to idealnie dla mnie. Myślę, że moim sposobem na uniknięcie zerowych wyjątków było użycie wartości zerowych, ale użyłem bardzo ograniczonego zakresu nazw metod (dosłownie tylko licznik od 1 do 4).
Jain Waldrip,
12
//Step1 - Using string funClass to convert to class
String funClass = "package.myclass";
Class c = Class.forName(funClass);

//Step2 - instantiate an object of the class abov
Object o = c.newInstance();
//Prepare array of the arguments that your function accepts, lets say only one string here
Class[] paramTypes = new Class[1];
paramTypes[0]=String.class;
String methodName = "mymethod";
//Instantiate an object of type method that returns you method name
 Method m = c.getDeclaredMethod(methodName, paramTypes);
//invoke method with actual params
m.invoke(o, "testparam");
anujin
źródło
8

Jeśli wykonasz to wywołanie kilka razy, możesz użyć nowych uchwytów metod wprowadzonych w Javie 7. Oto twoja metoda zwracająca ciąg znaków:

Object obj = new Point( 100, 200 );
String methodName = "toString";  
Class<String> resultType = String.class;

MethodType mt = MethodType.methodType( resultType );
MethodHandle methodHandle = MethodHandles.lookup().findVirtual( obj.getClass(), methodName, mt );
String result = resultType.cast( methodHandle.invoke( obj ) );

System.out.println( result );  // java.awt.Point[x=100,y=200]
Christian Ullenboom
źródło
1
Do przyszłych czytelników; Jeśli zależy Ci na wydajności, zechcesz korzystać z niej, invokeExactkiedy tylko możesz. W tym celu podpis witryny wywołującej musi jednak dokładnie odpowiadać typowi uchwytu metody. Zazwyczaj zajmuje trochę majsterkowania. W takim przypadku musisz rzucić pierwszy parametr za pomocą: methodHandle = methodHandle.asType(methodHandle.type().changeParameterType(0, Object.class));a następnie wywołać jakString result = (String) methodHandle.invokeExact(obj);
Jorn Vernee
7

To brzmi jak coś, co można zrobić z pakietem Java Reflection.

http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html

Szczególnie w części Wywoływanie metod według nazwy:

import java.lang.reflect. *;

public class method2 {
  public int add(int a, int b)
  {
     return a + b;
  }

  public static void main(String args[])
  {
     try {
       Class cls = Class.forName("method2");
       Class partypes[] = new Class[2];
        partypes[0] = Integer.TYPE;
        partypes[1] = Integer.TYPE;
        Method meth = cls.getMethod(
          "add", partypes);
        method2 methobj = new method2();
        Object arglist[] = new Object[2];
        arglist[0] = new Integer(37);
        arglist[1] = new Integer(47);
        Object retobj 
          = meth.invoke(methobj, arglist);
        Integer retval = (Integer)retobj;
        System.out.println(retval.intValue());
     }
     catch (Throwable e) {
        System.err.println(e);
     }
  }
}
zxcv
źródło
6

Indeksowanie (szybciej)

Możesz użyć FunctionalInterfacedo zapisania metod w kontenerze, aby je zindeksować. Możesz użyć kontenera tablic, aby wywoływać je za pomocą liczb lub haszapa, aby wywoływać je za pomocą ciągów. Dzięki tej sztuczce możesz indeksować swoje metody, aby wywoływać je dynamicznie szybciej .

@FunctionalInterface
public interface Method {
    double execute(int number);
}

public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        this::square,
        this::circle
    };

    private double square(int number) {
        return number * number;
    }

    private double circle(int number) {
        return PI * number * number;
    }

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(aNumber);
    }
}

Składnia lambda

Możesz także użyć składni lambda:

public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        number -> {
            return number * number;
        },
        number -> {
            return PI * number * number;
        },
    };

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(aNumber);
    }
}
Amir Fo
źródło
1
Ta technika wydaje się znacznie lepsza niż odbicie.
John O
Czy to naprawdę dużo lepsze?
Dimitri Kopriwa
@DimitriKopriwa Indeksowanie to sposób użycia pamięci RAM zamiast obliczeń procesora. W przypadku indeksowania liczb całkowitych trudność algorytmu wynosi O(1).
Amir Fo
5
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

SomeClassjest klasą i someVariablejest zmienną.

Subrahmanya Prasad
źródło
jeśli someVariable jest naprawdę obiektem, wywołaj someVariable.getClass (). Nie można również wywoływać metody getMethod () z klasą jako jedynym argumentem. Żadna z metod nie może wywoływać metody Prawidłowo: someVariable.getClass (). GetMethod („coolMethod”, parameterClasses) .invoke (argumenty);
Orangle
5

Robię to w ten sposób:

try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}
Marcel
źródło
5

Zapoznaj się z poniższym kodem, który może ci pomóc.

public static Method method[];
public static MethodClass obj;
public static String testMethod="A";

public static void main(String args[]) 
{
    obj=new MethodClass();
    method=obj.getClass().getMethods();
    try
    {
        for(int i=0;i<method.length;i++)
        {
            String name=method[i].getName();
            if(name==testMethod)
            {   
                method[i].invoke(name,"Test Parameters of A");
            }
        }
    }
    catch(Exception ex)
    {
        System.out.println(ex.getMessage());
    }
}

Dzięki....

Rahul Karankal
źródło
Nie tak porównujesz ciągi znaków w Javie. Musisz użyć metody .equals. W przeciwnym razie po prostu porównujesz, że są one tym samym odwołaniem do obiektu, i tak naprawdę nie obchodzi cię odwołanie do obiektu - tylko dopasowanie ciągu znaków. Możesz również uzyskać metodę według nazwy poprzez odbicie, więc nie wiesz, dlaczego rzucisz własną?
Lo-Tan
5

Oto GOTOWE DO UŻYCIA METODY:

Aby wywołać metodę bez argumentów:

public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    object.getClass().getDeclaredMethod(methodName).invoke(object);
}

Aby wywołać metodę za pomocą argumentów:

    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }

Użyj powyższych metod, jak poniżej:

package practice;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class MethodInvoke {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
        String methodName1 = "methodA";
        String methodName2 = "methodB";
        MethodInvoke object = new MethodInvoke();
        callMethodByName(object, methodName1);
        callMethodByName(object, methodName2, 1, "Test");
    }

    public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName).invoke(object);
    }

    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }

    void methodA() {
        System.out.println("Method A");
    }

    void methodB(int i, String s) {
        System.out.println("Method B: "+"\n\tParam1 - "+i+"\n\tParam 2 - "+s);
    }
}

Wynik:

Metoda A  
Metoda B:  
	Param 1 - 1  
	Param 2 - Test
Sandeep Nalla
źródło
3

Student.java

class Student{
    int rollno;
    String name;

    void m1(int x,int y){
        System.out.println("add is" +(x+y));
    }

    private void m3(String name){
        this.name=name;
        System.out.println("danger yappa:"+name);
    }
    void m4(){
        System.out.println("This is m4");
    }
}

StudentTest.java

import java.lang.reflect.Method;
public class StudentTest{

     public static void main(String[] args){

        try{

            Class cls=Student.class;

            Student s=(Student)cls.newInstance();


            String x="kichha";
            Method mm3=cls.getDeclaredMethod("m3",String.class);
            mm3.setAccessible(true);
            mm3.invoke(s,x);

            Method mm1=cls.getDeclaredMethod("m1",int.class,int.class);
            mm1.invoke(s,10,20);

        }
        catch(Exception e){
            e.printStackTrace();
        }
     }
}
użytkownik8387971
źródło
1

Powinieneś użyć refleksji - zainicjuj obiekt klasy, następnie metodę w tej klasie, a następnie wywołaj tę metodę na obiekcie z opcjonalnymi parametrami. Pamiętaj, aby owinąć następujący fragment kodu w bloku try-catch

Mam nadzieję, że to pomoże!

Class<?> aClass = Class.forName(FULLY_QUALIFIED_CLASS_NAME);
Method method = aClass.getMethod(methodName, YOUR_PARAM_1.class, YOUR_PARAM_2.class);
method.invoke(OBJECT_TO_RUN_METHOD_ON, YOUR_PARAM_1, YOUR_PARAM_2);
detman
źródło
1

To działa dobrze dla mnie:

public class MethodInvokerClass {
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, ClassNotFoundException, InvocationTargetException, InstantiationException {
        Class c = Class.forName(MethodInvokerClass.class.getName());
        Object o = c.newInstance();
        Class[] paramTypes = new Class[1];
        paramTypes[0]=String.class;
        String methodName = "countWord";
         Method m = c.getDeclaredMethod(methodName, paramTypes);
         m.invoke(o, "testparam");
}
public void countWord(String input){
    System.out.println("My input "+input);
}

}

Wynik:

My input testparam

Jestem w stanie wywołać metodę, przekazując jej nazwę do innej metody (np. Main).

Laxman G.
źródło
1

za pomocą import java.lang.reflect.*;

public static Object launchProcess(String className, String methodName, Class<?>[] argsTypes, Object[] methodArgs)
        throws Exception {

    Class<?> processClass = Class.forName(className); // convert string classname to class
    Object process = processClass.newInstance(); // invoke empty constructor

    Method aMethod = process.getClass().getMethod(methodName,argsTypes);
    Object res = aMethod.invoke(process, methodArgs); // pass arg
    return(res);
}

i oto jak z niego korzystasz:

String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class,  String.class};
Object[] methArgs = { "hello", "world" };   
launchProcess(className, methodName, argsTypes, methArgs);
dina
źródło
0

W jooR jest to po prostu:

on(obj).call(methodName /*params*/).get()

Oto bardziej skomplikowany przykład:

public class TestClass {

    public int add(int a, int b) { return a + b; }
    private int mul(int a, int b) { return a * b; }
    static int sub(int a, int b) { return a - b; }

}

import static org.joor.Reflect.*;

public class JoorTest {

    public static void main(String[] args) {
        int add = on(new TestClass()).call("add", 1, 2).get(); // public
        int mul = on(new TestClass()).call("mul", 3, 4).get(); // private
        int sub = on(TestClass.class).call("sub", 6, 5).get(); // static
        System.out.println(add + ", " + mul + ", " + sub);
    }
}

To drukuje:

3, 12, 1

Andronikus
źródło
-10

dla mnie dość prostym i głupim sposobem byłoby po prostu stworzenie metody wywołującej metodę, takiej jak:

public static object methodCaller(String methodName)
{
    if(methodName.equals("getName"))
        return className.getName();
}

wtedy, gdy musisz wywołać metodę, po prostu umieść coś takiego

//calling a toString method is unnessary here, but i use it to have my programs to both rigid and self-explanitory 
System.out.println(methodCaller(methodName).toString()); 
SMayne
źródło
4
Jeśli instancja jest już znana podczas kompilacji, dlaczego po prostu nie zrobisz tego className.getName().toString()? Brakuje ci całego punktu refleksji.
BalusC
Jak powiedziałem, niepotrzebne w tym przypadku, ale zakładając, że zawsze będziesz wiedział, że instancja jest złym nawykiem programistycznym.
SMayne
2
@SMayne: Proponuję usunąć ten post.
lpapp
złe programowanie byłoby raczej komplementem w tym przypadku
pdenti