java反射
Posted 小破孩楼主
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java反射相关的知识,希望对你有一定的参考价值。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能:
- 在运行时构造任意一个类的对象
- 在运行时获取任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法(属性)
- 生成动态代理
Class 是一个类; 一个描述类的类.
封装了描述方法的 Method,
package reflect; public class Person { String name; private int age; private Integer sal; public String getName() { return name; } public void setName(String name) { this.name = name; System.out.println("执行了setName()方法"); } public int getAge() { return age; } public void setAge(int age) { this.age = age; System.out.println("执行了setAge()方法"); } public Integer getSal() { return sal; } public void setSal(Integer sal) { this.sal = sal; System.out.println("执行了setAge()方法"); } public Person(String name, int age, Integer sal) { super(); this.name = name; this.age = age; this.sal = sal; } public Person() { super(); } private void Say(){ System.out.println("我好痛苦,我觉得生不如死!"); } public void test(String name,Integer sal){ System.out.println("调用成功"); } }
package reflect; public class Student extends Person{ private Double score; public Double getScore() { return score; } public void setScore(Double score) { this.score = score; } private void Study(){ System.out.println("我太累了,不想学习"); } }
1、如何描述方法-Method(getDeclaredMethod()不能获取父类方法 getMethod() 一般只能获取私有方法)
@Test public void testMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ Class clazz=Class.forName("reflect.Person"); //1、获取clazz对应类中的所有方法--方法数组1 Method[] methods=clazz.getMethods(); for(Method method:methods){ System.out.println(method.getName()); } System.out.println("-----------------------------------------------------"); //2、获取所有方法包括私有方法---方法数组2 methods=clazz.getDeclaredMethods(); for(Method method:methods){ System.out.println(method.getName()); } //3.1、获取指定的方法 //需要参数名称和参数列表,无参则不需要 //对于方法 public void setName(String name){} Method method=clazz.getDeclaredMethod("setName",String.class); System.out.println(method); //而对于方法public void setAge(int age){} method=clazz.getDeclaredMethod("setAge",int.class); System.out.println(method); method=clazz.getDeclaredMethod("setSal",Integer.class ); System.out.println(method); //4、执行方法 invoke() 第一个参数表示执行哪个对象的方法,剩下的参数是执行方法时需要转入的参数 Object obj=clazz.newInstance(); method.invoke(obj, 2000); //如果一个方法是私有方法,3.1是可以获取到的,但是这一步却不能执行 //私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true) method=clazz.getDeclaredMethod("Say",null); method.setAccessible(true); method.invoke(obj, null); }
主要用到的两个方法
/** * @param name the name of the method * @param parameterTypes the list of parameters * @return the {@code Method} object that matches the specified */ public Method getMethod(String name, Class<?>... parameterTypes){ } /** * @param obj the object the underlying method is invoked from * @param args the arguments used for the method call * @return the result of dispatching the method represented by */ public Object invoke(Object obj, Object... args){ }
自定义工具方法
自定义一个方法
把类对象和类方法名作为参数,执行方法
把全类名和方法名作为参数,执行方法
假设:Person类里面有一个方法
public void test(String name,Integer sal){ System.out.println("调用成功"); }
1. 把类对象和类方法名作为参数,执行方法(下面的方法没有考虑到无参的方法)
/** * @param obj: 方法执行的那个对象. * @param methodName: 类的一个方法的方法名. 该方法也可能是私有方法. * @param args: 调用该方法需要传入的参数 * @return: 调用方法后的返回值 * 把类对象和类方法名作为参数,执行方法 */ public Object invoke(Object obj,String methodName,Object ... args) throws Exception{ //1、获取Method对象 //因为getMethod的参数为Class类型,所以要把参数args转换为对应的Class类型 Class[] parameterTypes=new Class[args.length]; for(int i=0;i<args.length;i++){ parameterTypes[i]=args[i].getClass(); System.out.println(parameterTypes[i]); } Method method=obj.getClass().getDeclaredMethod(methodName, parameterTypes); //如果使用getDeclaredMethod(),就不能获取父类方法,如果使用getMethod()就不能获取私有方法 //2、执行Method方法 //返回方法返回值 return method.invoke(obj, args); }
@Test public void testInvoke() throws Exception{ Object obj=new Person(); invoke(obj,"test","李刚",20000); }
2.把全类名和方法名作为参数,执行方法(没有考考虑无参的方法)
public Object invoke(String className,String methodName,Object...args){ Object obj=null; try{ obj=Class.forName(className).newInstance(); return invoke(obj,methodName,args); }catch(Exception e){ e.printStackTrace(); } return null; }
这种反射实现的主要功能是可配置和低耦合。只需要类名和方法名,而不需要一个类对象就可以执行一个方法。如果我们把全类名和方法名放在一个配置文件中,就可以根据调用配置文件来执行方法
如何获取父类定义的(私有)方法
前面说一般使用getDeclaredMethod获取方法(因为此方法可以获取类的私有方法,但是不能获取父类方法)
如何获取父类方法呢,getMethod
首先我们要知道,如何获取类的父亲:
比如有一个类,继承自Person
@Test public void testGetSuperClass() throws Exception{ String className="reflect.Student"; Class clazz=Class.forName(className); Class superClazz=clazz.getSuperclass(); System.out.println(superClazz);//class reflect.Person }
此时如果Student中有一个方法是私有方法method1(int age); Person中有一个私有方法method2();
怎么调用 定义一个方法,不但能访问当前类的私有方法,还要能父类的私有方法
111111111111111111111
以上是关于java反射的主要内容,如果未能解决你的问题,请参考以下文章
使用反射在外部JAR / CLASS上调用包含Hibernate事务的方法(Java EE)