كيف يمكنني الاحتجاج طريقة جافا عندما تعطى الطريقة اسم سلسلة ؟
-
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());