java 反射 - 从入门到放弃

本贴最后更新于 1448 天前,其中的信息可能已经事过景迁

1、什么是反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 举个例子: 创建java对象时,一般是要知道类名,比如创建Student对象。 Student s = new Student(); 但是有些时候,当前时间不知道类名,我又想能创建这个类的对象,这时候就不需要用到反射。 只需要拿到字节码对象,我们就能通过反射获取对象、调用方法、访问变量。 从而脱离必须在java文件中把类名写死,java赋予的这种能力,广泛运用在各大流行框架中。

2、反射的应用场景

1. 封装对象(比如把excel中一行数据封装到一个自定义对象中) 2. 工具类(比如testng、fastjson) 3. Spring框架

3、反射优缺点

优点:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,避免将程序写死到代码里。 缺点:通过反射创建对象比直接写代码创建对象会慢一些,因为使用反射时进行一系列的安全性校验,加载字节码也会比较慢。

4、类加载过程

上面介绍了反射的优缺点,那为什么反射会比较慢呢?这就要说到类加载过程。 类加载机制: 加载--->链接(验证、准备、解析)--->初始化--->使用--->卸载 1. 加载:字节码.class文件加载到内存中 2. 链接: 1、验证字节码是否被篡改 2、准备分配对应的空间 3、解析字节码对应类的字段、父类、接口等 3. 初始化:相当于 new Student(); 创建类的对象 4. 使用:对象调用对象方法、字段等 5. 卸载:对象被回收

5、反射常用API

1、获取字节码对象

//Class.forName() Class clazz1 = Class.forName("com.lemon.Lemon"); //类名.class Class clazz2 = Lemon.class; //getClass() Lemon l = new Lemon(); Class clazz3 = l.getClass(); //通过三种方式获取的字节码对象都是相同,使用两两相等的方式比较。 System.out.println(clazz1 == clazz2); System.out.println(clazz1 == clazz3);

2、创建对象

//有两种方式可以创建对象,一用字节码调用newInstance(),二是先获取Constructor对象,在调用newInstance() Object o1 = clazz1.newInstance(); //获取Constructor //获取指定构造方法 Constructor constructor = clazz1.getConstructor(构造方法参数类型); //获取所有构造方法 Constructor[] constructors = clazz1.getConstructors(); //执行构造方法 Object o2 = constructor.newInstance(参数);

3、获取属性和方法

//获取字段 Field field = clazz1.getField(字段名称); Field[] fields = clazz1.getFields(); //设置字段 field.set(对象,字段值); //获取字段 Object value = filed.get(对象); //获取方法 Method method = clazz1.getMethod(方法名,方法参数类型); Method[] methods = clazz1.getMethods(); //执行方法 Object result = method.invoke(对象,方法参数):

4、暴力反射

//被private修饰的方法和字段只能在本类访问,但是通过反射可以强行获取,这在一定程度上破坏了封装性 //上面获取构造方法、字段、方法还有一组加了Declared修饰的方法,用它就能来访问所有内容(public、protected、默认、private) //Constructor getDeclaredConstructors(); getDeclaredConstructor(构造方法参数类型); //Field getDeclaredFields(); getDeclaredField(字段名称); //Method getDeclaredMethods(); getDeclaredMethod(方法名,方法参数类型); //当你获取到非公有内容还不能直接使用,还需要调用setAccessible(true)设置访问权限 constructor.setAccessible(true); field.setAccessible(true); method.setAccessible(true); //好了,这样就能用尽情的使用java类中所有成员了,哦也~
回帖
请输入回帖内容 ...