programing

메서드 이름을 문자열로 지정했을 때 Java 메서드를 호출하려면 어떻게 해야 합니까?

prostudy 2022. 9. 3. 09:17
반응형

메서드 이름을 문자열로 지정했을 때 Java 메서드를 호출하려면 어떻게 해야 합니까?

변수가 두 개일 경우:

Object obj;
String methodName = "getName";

obj에 의해 해야 합니까?methodName 위에 그 위에?

변수가 .String반환값자바빈을 위한 게터입니다.

엉덩이부터 코딩하면 다음과 같습니다.

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

에 의해 가능한된 여러 경우, " "만됩니다."methodName를 참조해 주세요.

그런 다음 호출하여 해당 메서드를 호출합니다.

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

한 번 ..invoke만약 없다면요.하지만 그래.Java Reflection에 대해 확인.

반사에서 메서드 호출 사용:

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

장소:

  • "class name"입니다.
  • objectToInvokeOn입니다.
  • "method name"입니다.
  • parameterTypes은 「」입니다.Class[] 메서드가 사용하는 합니다.
  • params은 「」입니다.Object[]합니다.

Java 7에서 간단한 코드 예를 원하는 경우:

Dog 링크:

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 링크:

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
    }
}

출력: Mishka is 3 year(s) old.


매개 변수를 사용하여 생성자를 다음과 같이 호출할 수 있습니다.

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

또는 다음 중 하나를 제거할 수 있습니다.

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

하고 있다

Dog dog = new Dog();

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

권장 자료: 새 클래스 인스턴스 만들기

메서드는 다음과 같이 호출할 수 있습니다.또한 더 많은 가능성이 있지만(reflection api 확인), 이것이 가장 간단한 방법입니다.

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);
    }



}

첫째, 하지 마세요.이런 종류의 코드는 피하세요.코드도 매우 나쁘고 안전하지 않은 경향이 있습니다(Java Programming Language, 버전 2.0의 Secure Coding Guidelines 섹션6 참조).

필요한 경우 리플렉션보다 java.beans를 선호합니다.비교적 안전하고 일반적인 접근을 가능하게 하는 반사를 감싸는 콩입니다.

동료의 답변을 완성하려면 다음 사항에 주의를 기울이는 것이 좋습니다.

  • 스태틱 콜 또는 인스턴스 콜(클래스의 인스턴스가 필요하지 않은 경우 또는 존재하지 않을 수 있는 기존 디폴트컨스트럭터에 의존할 필요가 있는 경우)
  • public 메서드콜 또는 non-public 메서드콜(후자의 경우 doPrivileged 블록 내의 메서드에 대해 setAccessible을 호출해야 합니다.다른 findbug는 행복하지 않습니다)
  • 다수의 Java 시스템 예외를 되돌리는 경우(따라서 다음 코드의 CCException)에 캡슐화됩니다.

다음은 이러한 점을 고려한 오래된 Java1.4 코드입니다.

/**
 * 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;
}
Object obj;

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

method.invoke(obj, null);
//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");

인덱싱(고속)

하시면 됩니다.FunctionalInterface컨테이너에 메서드를 저장하여 인덱싱합니다.어레이 컨테이너를 사용하여 어레이 컨테이너를 숫자로 호출하거나 해시 맵을 사용하여 어레이 컨테이너를 문자열로 호출할 수 있습니다.이 트릭을 사용하면 메서드를 인덱싱하여 동적으로 더 빠르게 호출할 수 있습니다.

@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(number);
    }
}

람다 구문

람다 구문을 사용할 수도 있습니다.

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(number);
    }
}

콜을 여러 번 실행하면 Java 7에서 도입된 새로운 메서드핸들을 사용할 수 있습니다.다음은 문자열을 반환하는 메서드입니다.

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]
try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}

Java Reflection 패키지로 실행할 수 있는 것 같습니다.

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

특히 이름에 의한 호출 메서드에서:

import java.displect.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);
     }
  }
}

사용 가능한 방법은 다음과 같습니다.

인수를 지정하지 않고 메서드를 호출하려면:

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);
    }

위의 방법을 다음과 같이 사용합니다.

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);
    }
}

출력:

방법 A방법 B:파라미터 1 - 1파라미터 2 - 테스트
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

SomeClass와 "class" 입니다.someVariable는 변수입니다.

도움이 될 수 있는 다음 코드를 참조하십시오.

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());
    }
}

감사합니다.

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");
    }
}

Student Test.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();
        }
     }
}

reflection - init 클래스 객체를 사용한 다음 이 클래스의 메서드를 사용하여 선택적 매개 변수를 사용하여 개체에 대해 이 메서드를 호출해야 합니다.다음 스니펫을 트라이캐치 블록에 랩하는 것을 잊지 마십시오.

도움이 됐으면 좋겠다!

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);

를 사용합니다.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);
}

사용 방법은 다음과 같습니다.

String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class,  String.class};
Object[] methArgs = { "hello", "world" };   
launchProcess(className, methodName, argsTypes, methArgs);

이 작업은 정상적으로 동작하고 있습니다.

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);
}

}

출력:

My input testparam

메서드의 이름을 다른 메서드(메인 등)로 전달함으로써 메서드를 호출할 수 있습니다.

jooR의 경우 다음과 같습니다.

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

다음은 보다 상세한 예를 제시하겠습니다.

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);
    }
}

다음의 출력이 있습니다.

3, 12, 1

같은 클래스 내의 메서드를 비정적 메서드에서 호출하는 사용자는 다음 코드를 참조하십시오.

class Person {
    public void method1() {
        try {
            Method m2 = this.getClass().getDeclaredMethod("method2");
            m1.invoke(this);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void method2() {
        // Do something
    }

}

같은 클래스 내의 정적 메서드에서 정적 메서드를 호출한다고 가정합니다.그러기 위해서, 다음의 코드를 샘플로 할 수 있습니다.

class MainClass
{
  public static int foo()
  {
    return 123;
  }

  public static void main(String[] args)
  {
    Method method = MainClass.class.getMethod("foo");
    int result = (int) method.invoke(null); // answer evaluates to 123
  }
}

한 객체 지향 때문에 하기 위해 '오브젝트'를 합니다.class를 호출하는 getMethod().

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.null★★★★★★★★★★★★★★★★의 경우invoke()이 작업을 수행할 개체가 없기 때문에 메서드를 지정합니다.

마지막으로 것을 알기 .invoke()정수로의 호출.

"이러한 오브젝트 지향 프로그래밍을 자바에서 하는 것이 무슨 의미가 있는가?"라는 의문이 들 수 있습니다.

저의 활용 사례는 프로젝트 오일러 문제를 자바에서 해결하는 것이었습니다.저는 모든 솔루션을 포함하는 단일 Java 소스 파일을 가지고 있으며, 어떤 Project Oiler 문제를 실행할지 결정하기 위해 명령줄 인수를 전달하고 싶었습니다.

나에게 있어서 꽤 간단하고 바보 같은 증명 방법은 단순히 다음과 같은 메서드 호출 방법을 만드는 것입니다.

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

그럼 메서드를 호출해야 할 때는 이렇게 간단히 입력해 주세요.

//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()); 

언급URL : https://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string

반응형