thinking in java反射
Posted five five open
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了thinking in java反射相关的知识,希望对你有一定的参考价值。
前言
反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件
概述
JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道这个类的所有信息,比如:成员变量、方法、构造方法、包等信息;要想用反射机制,首先要获取到
该类的字节码文件对象Class,然后用Class类中的方法把各种成分映射成Java对象,关于.class文件,在我们new对象的时候,本地IDE自动编译,然后jvm会自动的从硬盘
读取到.class文件,并创建一个该类的Class文件,但是,如果我们new了多个该类的实例,内存中只会有一份该类的字节码文件。
API
Class 类与 java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了 Field、Method、Constructor 类 (每个类都实现了 Member 接口)该接口反映单个成员(字段
或方法)或构造方法的标识信息,正因为实现了该接口,因此可以反射相关变量、方法信息,这些类型的对象时由 JVM 在运行时创建的,用以表示未知类里对应的成员。
反射
获取字节码
在 Java 中可以通过三种方法获取类的字节码 (Class) 对象,如下:
package com.oxygen.bean; public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException { Student student = new Student(); Class<?> clazz1 = student.getClass(); //方式1 Class<?> clazz2 = Student.class; //方式2 Class clazz3 = Class.forName("com.oxygen.student");//方式3 } }
获取类信息
Student类如下
View Code
1. 通过构造函数对象Constructor创建对应类的实例
package com.oxygen.bean; import java.lang.reflect.Constructor; public class ReflectTest { public static void main(String[] args) throws Exception { Student student = new Student(); //Student的带参构造函数依赖另外一个类Car Class<?> clazz1 = student.getClass(); //方式1 func1(clazz1); //通过无参构造函数反射Student实例 func2(clazz1);//通过有参构造函数反射Student实例 func3(clazz1);//获取所有的构造函数反射Student实例 func4(clazz1); // 反射私有构造函数 } private static void func4(Class<?> clazz1) throws Exception { Constructor<?> declaredConstructor = clazz1.getDeclaredConstructor(String.class); declaredConstructor.setAccessible(true);//设置为可以访问 System.out.println(declaredConstructor.newInstance("zhangsan")); } private static void func3(Class<?> clazz1) throws Exception { Constructor<?>[] constructors = clazz1.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("func3: " + constructor); } } /** * 因为Student的带参构造函数依赖另外一个类Car,因为必须保证JVM能获取到Car的字节码 * @param clazz1 * @throws Exception */ public static void func2(Class<?> clazz1) throws Exception { Car car = new Car();//保证 Constructor<?> constructor = clazz1.getConstructor(String.class, Integer.class, Car.class); Student student = (Student) constructor.newInstance("张三", 18, new Car()); System.out.println(student); } public static void func1(Class<?> clazz1) throws Exception { Constructor<?> constructor = clazz1.getConstructor(); Student student = (Student) constructor.newInstance(); System.out.println(student); } }
2. 获取成员方法
package com.oxygen.bean; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class ReflectTest { public static void main(String[] args) throws Exception { Student student = new Student(); Class<?> clazz1 = student.getClass(); m1(clazz1); m2(clazz1); m3(clazz1); m4(clazz1); } /** * 获取所有的方法,包括私有的,不包括继承Object类的9个方法 * @param clazz1 */ public static void m4(Class<?> clazz1) { Method[] declaredMethods = clazz1.getDeclaredMethods(); } /** * 获取所有的”公有“方法,包括继承Object类的9个方法 * @param clazz1 */ public static void m3(Class<?> clazz1) { Method[] methods = clazz1.getMethods(); } /** * 获取私有的show4()方法 * @param clazz1 * @throws Exception */ public static void m2(Class<?> clazz1) throws Exception { Method method; method = clazz1.getDeclaredMethod("show4", int.class); Student stu = func1(clazz1); // 实例化一个Student对象 method.setAccessible(true); method.invoke(stu, 20);//反射私有方法show4(),第一个参数是实例,第二个参数是被反射方法的参数 } /** * 获取公有的show1()方法 * @param clazz1 * @throws Exception */ public static void m1(Class<?> clazz1) throws Exception { Method method = clazz1.getMethod("show1", String.class); //第一个参数是方法名称,第二个参数是形参类型 Student stu = func1(clazz1); // 实例化一个Student对象 method.invoke(stu, "lisi"); //反射公有方法show1(),第一个参数是实例,第二个参数是被反射方法的参数 } public static Student func1(Class<?> clazz1) throws Exception { Constructor<?> constructor = clazz1.getConstructor(); Student student = (Student) constructor.newInstance(); return student; } }
以上是关于thinking in java反射的主要内容,如果未能解决你的问题,请参考以下文章