反射概述
Java反射机制:
- 是指在运行时去获取一个类的变量和方法信息。
- 然后通过获取的信息来创建对象,调用方法的一种机制。
- 由于这种,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。
获取Class类的对象
案例:- //Student类
- public class Student {
- /**
- * 成员变量:私有,默认,公共
- */
- private String name;
- int age;
- public String address;
- //构造方法:一个私有,一个默认,两个公共
- public Student() {
- }
- private Student(String name) {
- this.name = name;
- }
- Student(String name, int age) {
- this.name = name;
- this.age = age;
- }
- public Student(String name, int age, String address) {
- this.name = name;
- this.age = age;
- this.address = address;
- }
- /**
- * 成员方法:一个私有,四个公共
- */
- private void function() {
- System.out.println("function");
- }
- public void method1() {
- System.out.println("method");
- }
- public void method2(String s) {
- System.out.println("method:" + s);
- }
- public String method3(String s, int i) {
- return s + "," + i;
- }
- @Override
- public String toString() {
- return "Student{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", address='" + address + '\'' +
- '}';
- }
- }
复制代码- public class Demo {
- public static void main(String[] args) throws ClassNotFoundException {
- //使用类的class属性获取该类对应的Class对象
- Class<Student> c1 = Student.class;
- System.out.println(c1);
- //一个类在内存中只有一个字节码文件对象
- Class<Student> c2 = Student.class;
- System.out.println(c1 == c2);
- System.out.println("-------------------");
- /*通过调用对象的getClass()方法,返回对象所属类的class对象
- 该方法是Object类中的方法,所有的Java对象都可以调用该方法*/
- Student stu = new Student();
- Class<? extends Student> c3 = stu.getClass();
- System.out.println(c1 == c3);
- System.out.println("-------------------");
- //使用Class类中的静态方法forName(String className),返回对象所属类的class对象
- Class<?> c4 = Class.forName("com.fanshe.Student");
- System.out.println(c1 == c4);
- }
- }
复制代码 运行结果:- class com.fanshe.Student
- true
- -------------------
- true
- -------------------
- true
复制代码 反射获取构造方法并使用
- getConstructors():返回一个数组,包含该Class对象中的public公共构造函数
- getDeclaredConstructors():返回一个数组,包含该Class对象中的所有构造函数
- getConstructor(参数列表):获取指定的公共构造函数对象
- getDeclaredConstructor(参数列表):获取指定的构造函数对象
- newInstance(参数):构造方法创建对象
- setAccessible(boolean flag):值为true时取消访问检查
练习:- public class Demo2 {
- public static void main(String[] args) throws Exception {
- //获取Class对象
- Class<?> c = Class.forName("com.fanshe.Student");
- //getConstructors():返回一个数组,包含该Class对象中的public公共构造函数
- Constructor<?>[] cons = c.getConstructors();
- System.out.println("公共构造函数:");
- for (Constructor<?> con : cons) {
- System.out.println(con);
- }
- //getDeclaredConstructors():返回一个数组,包含该Class对象中的所有构造函数
- Constructor<?>[] dCons = c.getDeclaredConstructors();
- System.out.println("所有构造函数:");
- for (Constructor<?> dCon : dCons) {
- System.out.println(dCon);
- }
- System.out.println("指定的公共构造函数1:");
- //getConstructor():返回指定的公共构造函数的对象
- //参数:构造方法的参数 和 数据类型对应的字节码文件对象(Class对象)
- Constructor<?> con = c.getConstructor();
- //公共构造函数的对象使用newInstance()创建实例对象
- //newInstance():构造方法创建对象
- Object obj = con.newInstance();
- System.out.println(obj);
- System.out.println("指定的公共构造函数2:");
- //基本数据类型 也可以通过.class 得到对应的Class类型
- System.out.println(c.getConstructor(String.class, int.class, String.class).newInstance("李白",22,"西安"));
- System.out.println("指定的构造函数");
- //getDeclaredConstructor():获取指定的构造函数
- //参数:构造方法的参数 和 数据类型对应的字节码文件对象(Class对象)
- Constructor<?> dCon = c.getDeclaredConstructor(String.class);
- //setAccessible():值为true时取消访问检查
- dCon.setAccessible(true);
- System.out.println(dCon.newInstance("杨玉环"));
- }
- }
复制代码 运行结果:- 公共构造函数:
- public com.fanshe.Student(java.lang.String,int,java.lang.String)
- public com.fanshe.Student()
- 所有构造函数:
- public com.fanshe.Student(java.lang.String,int,java.lang.String)
- com.fanshe.Student(java.lang.String,int)
- private com.fanshe.Student(java.lang.String)
- public com.fanshe.Student()
- 指定的公共构造函数1:
- Student{name='null', age=0, address='null'}
- 指定的公共构造函数2:
- Student{name='李白', age=22, address='西安'}
- 指定的构造函数
- Student{name='杨玉环', age=0, address='null'}
复制代码 反射获取成员变量并使用
Class类中用于获取成员变量的方法
- getFields():获取公共的成员变量
- getDeclaredFields():获取所有的成员变量
- getField(成员变量):获取指定的公共成员变量
- getDeclaredField(成员变量):获取指定的成员变量
Field类中,给成员变量赋值的方法
- set(Object obj,Object value):给obj方法实例中的成员变量赋值
练习:- public class Demo3 {
- public static void main(String[] args) throws Exception {
- //获取Class对象
- Class<?> c = Class.forName("com.fanshe.Student");
- //getFields():获取公共的成员变量
- Field[] fields = c.getFields();
- System.out.println("获取公共的成员变量:");
- for (Field field : fields) {
- System.out.println(field);
- }
- //getDeclaredFields():获取所有的成员变量
- Field[] df = c.getDeclaredFields();
- System.out.println("获取所有的成员变量:");
- for (Field field : df) {
- System.out.println(field);
- }
- System.out.println("获取指定的公共成员变量并赋值,再创建对象:");
- //获取指定的公共成员变量
- Field addressField = c.getField("address");
- //获取指定的公共构造方法,并创建方法实例
- Object obj = c.getConstructor().newInstance();
- //给方法中的成员变量赋值
- addressField.set(obj,"西安");
- //输出方法实例(对象)
- System.out.println(obj);
- System.out.println("获取指定的公共构造函数对象,再实例化对象:");
- //获取单个公共方法
- Constructor<?> con = c.getConstructor();
- //创建方法实例
- Object obj1 = con.newInstance();
- System.out.println(obj1);
- System.out.println("获取指定的成员变量并赋值,再实例化对象:");
- //获取指定的成员变量
- Field nameField = c.getDeclaredField("name");
- Field ageField = c.getDeclaredField("age");
- Field addField = c.getDeclaredField("address");
- //取消访问检查
- nameField.setAccessible(true);
- ageField.setAccessible(true);
- addField.setAccessible(true);
- //给成员变量赋值
- nameField.set(obj1,"胡辣汤");
- ageField.set(obj1,10);
- addField.set(obj1,"北京");
- //输出对象
- System.out.println(obj1);
- }
- }
复制代码 运行结果:- 获取公共的成员变量:
- public java.lang.String com.fanshe.Student.address
- 获取所有的成员变量:
- private java.lang.String com.fanshe.Student.name
- int com.fanshe.Student.age
- public java.lang.String com.fanshe.Student.address
- 获取指定的公共成员变量并赋值,再创建对象:
- Student{name='null', age=0, address='西安'}
- 获取指定的公共构造函数对象,再实例化对象:
- Student{name='null', age=0, address='null'}
- 获取指定的成员变量并赋值,再实例化对象:
- Student{name='胡辣汤', age=10, address='北京'}
复制代码 反射获取成员方法并使用
Class类中用于获取成员方法的方法
- getMethods():获取全部的公共成员方法数组,包含继承的方法
- getDeclaredMethods():获取全部的成员方法数组,不包含继承的方法
- getMethod("方法名",参数类型.class):获取单个公共成员方法对象
- getDeclaredMethod("方法名",参数类型.class):获取单个成员方法对象
Method类中用于调用成员方法的方法
- invoke(实体类对象,方法参数列表):调用实体类对象的成员方法
练习:- public class Demo4 {
- public static void main(String[] args) throws Exception {
- //获取Class对象
- Class<?> c = Class.forName("com.fanshe.Student");
- System.out.println("获取全部的公共成员方法:");
- //getMethods():获取全部的公共成员方法,包含继承的方法
- Method[] methods = c.getMethods();
- for (Method method : methods) {
- System.out.println(method);
- }
- System.out.println("获取全部的成员方法:");
- //getDeclaredMethods():获取全部的成员方法,不包含继承的方法
- Method[] dms = c.getDeclaredMethods();
- for (Method dm : dms) {
- System.out.println(dm);
- }
- System.out.println("获取单个的公共成员方法1:");
- //getMethod("方法名",参数类型.class):获取单个的公共成员方法对象
- Method method1 = c.getMethod("method1");
- //获取无参构造方法,创建实体类对象
- Object obj1 = c.getConstructor().newInstance();
- //invoke(实体类对象,方法参数列表):调用对象的成员方法
- method1.invoke(obj1);
- System.out.println("获取单个的公共成员方法2:");
- Method method2 = c.getMethod("method2",String.class);
- method2.invoke(obj1,"马超");
- System.out.println("获取单个的公共成员方法3:");
- Method method3 = c.getMethod("method3", String.class, int.class);
- //有返回值,先接收一下
- Object obj2 = method3.invoke(obj1, "赵云", 22);
- //输出返回结果
- System.out.println(obj2);
- System.out.println("获取单个的成员方法:");
- //getDeclaredMethod("方法名",参数类型):获取单个的成员方法对象
- Method dm = c.getDeclaredMethod("function");
- //取消访问检查
- dm.setAccessible(true);
- dm.invoke(obj1);
- }
- }
复制代码 运行结果:- 获取全部的公共成员方法:
- public java.lang.String com.fanshe.Student.toString()
- public void com.fanshe.Student.method1()
- public java.lang.String com.fanshe.Student.method3(java.lang.String,int)
- public void com.fanshe.Student.method2(java.lang.String)
- public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
- public final void java.lang.Object.wait() throws java.lang.InterruptedException
- public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
- public boolean java.lang.Object.equals(java.lang.Object)
- public native int java.lang.Object.hashCode()
- public final native java.lang.Class java.lang.Object.getClass()
- public final native void java.lang.Object.notify()
- public final native void java.lang.Object.notifyAll()
- 获取全部的成员方法:
- public java.lang.String com.fanshe.Student.toString()
- private void com.fanshe.Student.function()
- public void com.fanshe.Student.method1()
- public java.lang.String com.fanshe.Student.method3(java.lang.String,int)
- public void com.fanshe.Student.method2(java.lang.String)
- 获取单个的公共成员方法1:
- method
- 获取单个的公共成员方法2:
- method:马超
- 获取单个的公共成员方法3:
- 赵云,22
- 获取单个的成员方法:
- function
复制代码 反射练习-越过泛型检查
如何实现在ArrayList< Integer >集合中添加一个字符串数据?
- public class Demo5 {
- public static void main(String[] args) throws Exception {
- //创建集合
- ArrayList<Integer> list = new ArrayList<>();
- //添加数据
- list.add(10);
- list.add(20);
- list.add(30);
- //输出集合
- System.out.println(list);
- //利用反射,在list中添加一个String数据
- Class<? extends ArrayList> lc = list.getClass();
- Method ad = lc.getMethod("add", Object.class);
- ad.invoke(list,"hello");
- //输出添加String数据后的集合
- System.out.println(list);
- }
- }
复制代码 运行结果:- [10, 20, 30]
- [10, 20, 30, hello]
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |