Java Method的invoke委托

Java Method的invoke委托

@author ixenos

Class对象运行时构造并委托调用方法(Method类)



0.由Class对象动态构造对应类型对象

1.Class对象的getMethod方法,由方法名和形参构造Method对象

2.Method对象的invoke方法来委托动态构造的对应类型对象,使其执行对应形参的add方法

//动态构造InvokeTest类的实例Class<?> classType = InvokeTest.class;
Object invokeTest = classType.newInstance();

//动态构造InvokeTest类的add(int num1, int num2)方法,标记为addMethod的Method对象
Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});

//动态构造的Method对象invoke委托动态构造的InvokeTest对象,执行对应形参的add方法Object result = addMethod.invoke(invokeTest, new Object[]{1, 2});

//测试输出
System.out.println((Integer)result);

public Method getMethod(String name,
                        Class<?>... parameterTypes)
                 throws NoSuchMethodException,
                        SecurityException返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypes 为 null,则按空数组处理。
如果 name 是 "<init>;" 或 "<clinit>",则将引发 NoSuchMethodException。否则,要反映的方法由下面的算法确定(设 C 为此对象所表示的类): 

在 C 中搜索任一匹配的方法。如果找不到匹配的方法,则将在 C 的超类上递归调用第 1 步算法。
如果在第 1 步中没有找到任何方法,则在 C 的超接口中搜索匹配的方法。如果找到了这样的方法,则反映该方法。
在 C 类中查找匹配的方法:如果 C 正好声明了一个具有指定名称的公共方法并且恰恰有相同的形参类型,则它就是反映的方法。如果在 C 中找到了多个这样的方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则反映该方法;否则将从中任选一个方法。
注意,类中可以有多个匹配方法,因为尽管 Java 语言禁止类声明带有相同签名但不同返回类型的多个方法,但 Java 虚拟机并不禁止。这增加了虚拟机的灵活性,可以用来实现各种语言特性。例如,可以使用桥方法 (brige method)实现协变返回;桥方法以及将被重写的方法将具有相同的签名,不同的返回类型。 

请参阅Java 语言规范 第 8.2 和 8.4 节。 

参数:
name - 方法名
parameterTypes - 参数列表
返回:
与指定的 name 和 parameterTypes 匹配的 Method 对象
抛出:
NoSuchMethodException - 如果找不到匹配的方法,或者方法名为 "<init>" 或 "<clinit>"
NullPointerException - 如果 name 为 null
SecurityException - 如果存在安全管理器 s,并满足下列任一条件:
调用 s.checkMemberAccess(this, Member.PUBLIC) 拒绝访问方法
调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包 

API-Class-getMethod

public Object invoke(Object obj,
                     Object... args)
              throws IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。
如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。 

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。 

如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。 

如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。 

如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。 

参数:
obj - 从中调用底层方法的对象
args - 用于方法调用的参数
返回:
使用参数 args 在 obj 上指派该对象所表示方法的结果
抛出:
IllegalAccessException - 如果此 Method 对象强制执行 Java 语言访问控制,并且底层方法是不可访问的。
IllegalArgumentException - 如果该方法是实例方法,且指定对象参数不是声明底层方法的类或接口(或其中的子类或实现程序)的实例;如果实参和形参的数量不相同;如果基本参数的解包转换失败;如果在解包后,无法通过方法调用转换将参数值转换为相应的形参类型。
InvocationTargetException - 如果底层方法抛出异常。
NullPointerException - 如果指定对象为 null,且该方法是一个实例方法。
ExceptionInInitializerError - 如果由此方法引起的初始化失败。

API-Method-invoke

用反射实现获得运行时对象的拷贝的方法(Field类)



 1 import java.lang.class;
 2 import java.lang.reflect;
 3
 4  public class ReflectTester
 5 {
 6   public Object copy(Object object) throws Exception
 7   {
 8     Class<?> classType = object.getClass();
 9     Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
10     //获得对象的所有成员变量
11     Field[] fields = classType.getDeclaredFields();
12     for(Field field : fields)
13     {
14       String name = field.getName();
15       //将属性的首字母转换为大写
16       String firstLetter = name.substring(0,1).toUpperCase();
17       //substring(1)表示从index=1开始到最后的子字符串
18       String getMethodName = "get" + firstLetter + name.substring(1);
19       String setMethodName = "set" + firstLetter + name.substring(1);
20       Method getMethod = classType.getMethod(getMethodName, new Class[] {});
21       Method setMethod = classType.setMethod(getMethodName, new Class[] { field.getType() });
22       Object value = getMethod.invoke(object, new Object[] {});
23       setMethod.invoke(objectCopy, new Object[] { value });
24     }
25     return objectCopy;
26   }
27   public static void main(String[] args)
28   {
29     Customer customer = new Customer("Tom", 20);
30     customer.setId(1L);
31
32     ReflectTester test = new ReflectTester();
33     Customer customer2 = (Customer) test.copy(customer);
34     System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());
35   }
36 }
37
38 Class Customer
39 {
40   private float ID;
41   private String name;
42   private int age;
43   public Customer()
44   {
45     this.ID = 1L;
46     this.name = A;
47     this.age = 1;
48   }
49   public Customer(String name, int age)
50   {
51     this();
52     this.name = name;
53     this.age = age;
54   }
55   public void setID(float ID)
56   {
57     this.ID = ID;
58   }
59 }

0.利用Class对象得到对应类型对象

1.利用Class对象的getDeclaredFields方法,得Field[]数组

2.遍历Field[]数组,构造每一个属性名的字符串,使首字母大写,再连接get字符串,组成setter和getter的命名

3.遍历的同时,getMethod,参数便是要构建的方法名和形参类型,得到各属性的setter和getter方法的Method对象

4.同时,得到方法后,调用各Method对象的invoke委托对应类型对象执行方法(有实参传入,或返回值)

时间: 2024-10-13 09:57:27

Java Method的invoke委托的相关文章

JAVA深入研究——Method的Invoke方法。

在写代码的时候,发现从父类class通过getDeclaredMethod获取的Method可以调用子类的对象,而子类改写了这个方法,从子类class通过getDeclaredMethod也能获取到Method,这时去调用父类的对象也会报错.虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java是如何实现的,就学习了下Method的源代码. Method的invoke方法 1.先检查 AccessibleObject的override属性是否为true. Accessibl

JAVA深入研究——Method的Invoke方法

http://www.cnblogs.com/onlywujun/p/3519037.html 在写代码的时候,发现Method可以调用子类的对象,但子类即使是改写了的Method,方法名一样,去调用父类的对象也会报错,虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java是如何实现的,就学习了下Method的源代码. Method的invoke方法 1.先检查 AccessibleObject的override属性是否为true. AccessibleObject是Met

JAVA深入研究——Method的Invoke方法(转)

在写代码的时候,发现Method可以调用子类的对象,但子类即使是改写了的Method,方法名一样,去调用父类的对象也会报错,虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java是如何实现的,就学习了下Method的源代码. Method的invoke方法 1.先检查 AccessibleObject的override属性是否为true. AccessibleObject是Method,Field,Constructor的父类,override属性默认为false,可调用s

用java语言实现事件委托模式

http://blog.csdn.net/yanshujun/article/details/6494447 用java语言实现事件委托模式 2010-04-27 00:04 2206人阅读 评论(11) 收藏 举报 java语言游戏object设计模式date 事件委托模式是一个比较常用的设计模式,但是Java语言本身没有对其做一定的封装,因此实现起来有一定难度(了解原理后很简单),相比之下.NET就容易了很多. 身为一个Java爱好者,怎么向这样一个小困难低头,但是上网搜索,却没发现相关解决

Calling a Java Method from Native Code

http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html Calling Java Methods This section illustrates how you can call Java methods from native methods. Our example program, Callbacks.java, invokes a native method. The native

测者的测试技术手册:揭开java method的一个秘密--巨型函数

揭开java method的一个秘密:巨型函数 相信,很多人都不知道Java的Method的上限为64K.本文将超过这个上限的函数叫做巨型函数. 巨型函数的问题 1.如果代码超过了这个限制,Java编译器就报"Code too large to complier"的错误. 2.代码并没有超过64K的限制,但是在运行时由于其他工具或者library使得对应的代码超过了64K的限制,那么Java会给我们一个java.lang.VerifyError的错误. 巨型函数是怎么来的 如下一些仅仅

Java Method Overriding --- runtime polymorphism ! not overloading

ref: http://www.studytonight.com/java/method-overriding-in-java.php                     Method Overriding between parent and child The key benefit of overriding is the ability to define method that's specific to a particular subclass type class Anima

java反射的invoke方法

首先简单介绍两个元注解:@retention是() 括号内参数作用时间 编译.运行.源码@target()  括号内参数作用范围 变量,方法.... //获取class对象 Class clazz = Class.forName("cn.ph.test.UserDao"); //获取对象方法 Method[] mds = clazz.getMethods(); //遍历 for(Method md : mds){ /** *@MyTest.class 注解码对象 *invake(Obj

java method demo,java方法演示

package myjavaproject; public class methoddemo { public static void main(String args[]) { print1(); System.out.println("I like Java!"); print1(); } public static void print1() { for (int i = 0; i < 19; i++) { System.out.print("*");