كيف يمكنني الاحتجاج طريقة جافا عندما تعطى الطريقة اسم سلسلة ؟

StackOverflow https://stackoverflow.com/questions/160970

  •  03-07-2019
  •  | 
  •  

سؤال

إذا كان لدي اثنين من المتغيرات:

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

نصائح أخرى

استخدام استدعاء الأسلوب من التفكير:

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[] ويعلن المعلمات التي تم تمريرها إلى الأسلوب

بالنسبة لأولئك الذين يريدون مستقيم إلى الأمام المثال التعليمات البرمجية في جافا 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, ...);

اقترح القراءة: إنشاء فئة جديدة حالات

ويمكن استدعاء أسلوب من هذا القبيل. وهناك أيضا المزيد من الإمكانيات (مراجعة المعهد انعكاس)، ولكن هذا هو أبسط واحد:

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



}

أولا، لا. تجنب هذا النوع من التعليمات البرمجية. أنه يميل إلى أن يكون كود سيئة حقا، وآمن جدا (انظر القسم 6 من الآمنة الترميز المبادئ التوجيهية ل جافا لغة برمجة، الإصدار 2.0 ).

<الإضراب> إذا كان يجب أن تفعل ذلك، ويفضل java.beans للتفكير. الفاصوليا يلتف انعكاس السماح بالوصول الآمن نسبيا والتقليدية.

لاستكمال زميلي إجابات ، قد تحتاج إلى إيلاء اهتمام وثيق إلى:

  • ثابت أو مثيل المكالمات (في حالة واحدة ، لا تحتاج مثيل من فئة أخرى ، قد تحتاج إلى الاعتماد على القائمة منشئ افتراضي التي قد أو قد لا يكون هناك)
  • عامة أو غير عامة استدعاء الأسلوب (لهذا الأخير ، تحتاج إلى استدعاء setAccessible على طريقة داخل doPrivileged كتلة, وغيرها findbugs لن تكون سعيدة)
  • تغليف في أحد أكثر قابلية للإدارة تطبيقية استثناء إذا كنت ترغب في رمي مرة أخرى عديدة جافا نظام الاستثناءات (ومن 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");

إذا قمت بذلك مرات عدة الدعوة يمكنك استخدام الطريقة الجديدة مقابض قدم في جاوة 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]

هذا يبدو وكأنه شيء غير قابلة للتنفيذ مع جافا انعكاس الحزمة.

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

خاصة في ظل استدعاء أساليب بالاسم:

java.لانغ.تعكس.*;

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);
     }
  }
}
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

وSomeClass هي الطبقة وsomeVariable هو متغير.

وأفعل هذا من هذا القبيل:

try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}

تجدر الإشارة البرمجية التالية قد تساعدك.

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

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

ويجب عليك استخدام انعكاس - الحرف الأول كائن فئة، ثم أسلوب في هذه الفئة، ثم استدعاء هذا الأسلوب على كائن مع اختياري المعلمات. تذكر أن التفاف المقتطف التالي في محاولة اللحاق كتلة

ونأمل أن يساعد!

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

وهذه الغرامة يعمل بالنسبة لي:

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

وأنا قادر على استدعاء الأسلوب عن طريق تمرير اسمها إلى طريقة أخرى (مثل الرئيسية).

وباستخدام 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 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);
    }
}

الإخراج:

Method A  
Method B:  
	Param1 - 1  
	Param 2 - Test

وبالنسبة لي وسيلة إثبات بسيطة جدا وأحمق سيكون لجعل مجرد وسيلة المتصل طريقة مثل ذلك:

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()); 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top