- java反射的概念
- 在Java中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。简单的说,反射机制就是在程序的运行过程中被允许对程序本身进行操作,比如自我检查,进行装载,还可以获取类本身,类的所有成员变量和方法,类的对象,还可以在运行过程中动态的创建类的实例,通过实例来调用类的方法,这就是反射机制一个比较重要的功能了。
- 理解反射机制,首先要理解类的加载过程
- 加载过程图
-
在Java程序执行的时候,要经历三个步骤:加载、连接和初始化。首先程序要加载到JVM的方法区中,然后进行连接,最后初始化。这里就主要介绍一下类的加载。如上图,首先,JVM会从硬盘中读取Java源文件并将其加载到方法区中同时生成类名.class文件,也就是类对象,这个类对象中包含了我们创建类的实例时所需要的模板信息,也就是源代码中的成员变量和方法等。Class本身也是一个类,它的主要功能之一就是生成类加载时的class文件,为类的初始化及实例化做准备。而我们在程序中通过关键字new创建的对象创建的是类的对象,而不是类对象,二者的区别如图中所示。
- 原理模型
- 常用的反射类以及用法
- java.lang.class
-
(调用某个对象的getClass()方法
User user=new User()
Class clazz=user.getClass() -
调用某个类的class属性来获取该类对应的Class对象
Class clazz=User.class -
调用包的地址
Calss clazz=Class.forName("")
-
- java.lang.reflect.Method
-
获取类的所有方法信息getDeclaredMethods()
-
获取类的公有方法信息getMethods()
-
要注意的是,在暴力获取私有方法后还要获取调用该方法的权限:.setAccessible(true)(默认false,需要设置成true)
-
- java.lang.reflect.fields
-
获取类的所有成员属性信息getDeclaredFields()
-
获取类的公有成员属性信息getFields()
-
- java.lang.reflect.constructor
-
获取类的所有构造方法信息getDeclaredConstructors()
-
获取类的公有构造方法信息getConstructors()
-
- java.lang.class
- 创建实例的两种方式
-
使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的 空构造器。
-
先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建 Class对象对应类的实 例,通过这种方法可以选定构造方法创建实例。
-
- Java反射优缺点
-
Java反射优点:在运行期确定对象、绑定对象、操作对象,最大限度的发挥了Java的灵活性。
-
Java反射缺点:反射相当于一系列解释操作,通知jvm要做的事情,性能相对较低。反射会跳过类型检查等,导致安全性问题。例如通过反射跳过泛型的编译前类型检查
-
- 应用场景
-
框架中的xml,properties等配置
-
框架中注解的使用
-
动态代理、AOP
-
JDBC数据库连接
-
- 例子
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import com.javasm.lang.Person; public class PersonTest3 { /** * 操作类的属性/成员变量 * 操作方法---->操作Method类 * 操作构造---->操作Constructor类 */ public static void test1() { try { Person person = new Person(); //1.创建Class类的实例 Class clazz = Class.forName("com.lj.bean.Person");//类或者接口的全限定名称 包名+类名 Method[] methods = clazz.getMethods();//只获得public方法(包含从父类继承的) System.out.println(Arrays.toString(methods)); methods = clazz.getDeclaredMethods();//只获得本类里面public/protected/默认/private System.out.println(Arrays.toString(methods)); // String 方法名 parameterTypes:参数类型 可变参数 >=0实参 //对name赋值 setName Method method = clazz.getMethod("setName", String.class); //运行方法 Object obj = method.invoke(person, "张三");//方法的参数数据 System.out.println(obj); System.out.println("person:"+person.getName()); System.out.println("------------------------------"); //执行b方法 method = clazz.getDeclaredMethod("b", String.class,Integer.class); method.setAccessible(true); obj = method.invoke(person, "hello world",100); System.out.println(obj); } catch (ClassNotFoundException|NoSuchMethodException|SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException |IllegalArgumentException |InvocationTargetException e) { e.printStackTrace(); } } public static void main(String[] args) { test1(); } }