认识Java反射
反射是什么
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
知道一个概念:动态加载类
动态加载:程序只有在运行时才会知道程序创建的对象。
静态加载:程序在编译的时候已经知道程序的运行结果,即创建的对象。
动态加载的好处是:当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器 ,不言而喻了。
java的反射机制就是这样增加程序的灵活性,避免将程序写死到代码里。
利用反射机制获取类
获取类的三种方法
已知一个Student类:
—.通过对象名.getClass()获得
Student stu = new Student(); //创建一个类的对象
Class clazz = stu.getClass(); //获取class对象
二.通过类名.class获得
Class clazz = Student.class; //获取class对象
三.通过Class.forName(“全类名”)
Class clazz = Class.forName(“全类名”) //获取class对象.此字符串必须是真实路径(包名.类名)
注:程序在运行中一个类只有一个class对象产生;所有反射获取类的方法都是从Class开始;这个class对象其实是一个类的字节码信息。
第三种方法是最常用的,也最能体现反射的本质。这个全类名字符串可以传入也可写在配置文件中等多种方法
动态创建类的实例对象
利用 类名.newInstance(),调用的类必须有无参构造器,否则创建失败
Object obj = clazz.newInstance();
也可以是Constructor声明类的新实例对象。
利用反射读取方法
类中的方法有公有和私有。私有的方法需要获得读取权限。见下文。
利用反射获取构造器并使用
批量获取构造器
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
获取单个特定的构造器
-
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法: 如:Class[] p={String.class,int.class}; //具有两个参数的构造器 Constructor cons1 = cls.getConstructor(p); //获取特定参数类型的构造器(共有方法)
-
调用构造方法,需给有参的构造方法传参public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有; 如:Class[] p={int.class}; Constructor cons = cls.getDeclaredConstructor(p);
Object obj1 = cons1.newInstance(“小红”,22);
Object obj = cons.newInstance(14);
利用反射获取成员方法并调用
批量获取构造器
public Method[] getMethods(): 获取所有"公有方法";(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods(): 获取所有的成员方法,包括私有的(不包括继承的)
获取单个特定的构造器
-
public Method getMethod(String name,Class<?>... parameterTypes): 单个共有的成员方法 参数: name : 方法名; Class ... : 形参的Class类型对象
-
public Method getDeclaredMethod(String name,Class<?>... parameterTypes): 单个公有、私有、保护的成员方法 参数: name : 方法名; Class ... : 形参的Class类型对象 如:String name="three"; //Student类中有一个three(String )的私有方法 Class[] types={String.class}; //Class[]类型列表;A.class表示A的类型 Method method = cls.getDeclaredMethod(name, types); //根据方法名和参数类型 获取特定私有方法 method.setAccessible(true); ##解除私有限定,否则运行出错 System.out.println(method); //调用私有方法three() Object objs = cls.newInstance(); //创建实例,执行了构造方法 method.invoke(objs,"小强"); //invoke()第一个参数是类的实例,第二个是方法参数
利用反射获取成员变量并调用
批量获取成员方法
Field[] getFields(): 获取所有的"公有字段"
Field[] getDeclaredFields(): 获取所有字段,包括:私有、受保护、默认、公有;
获取单个成员方法
Field getField(String fieldName):获取所有的"公有字段"
Field getDeclaredField(String fieldName):获取所有字段,包括:私有、受保护、默认、公有;
如://获取类的私有字段age
Field field = cls.getDeclaredField("age");
field.setAccessible(true);
System.out.println("Field found: " + field.toString());
System.out.println("Field found: " + field.get(objs).toString());
//修改字段的值
field.set(objs, 25);
System.out.println("Field found: " + field.toString());
System.out.println("Field found: " + field.get(objs).toString());
结果:Field found: private int demo.myReflect.age
Field found: 20
Field found: private int demo.myReflect.age
Field found: 25
动态执行方法invoke()
- Object obj =method.invoke(对象,方法参数1,方法参数2, …)
— invoke()第一个参数是类的实例,第二个是方法参数 - 在反射中利用invoke()可以调用私有方法。
- invoke有返回值,返回被调用方法执行的结果,对象后面的参数是执行方法时候传递的参数。