Java-反射

打印 上一主题 下一主题

主题 803|帖子 803|积分 2409

反射概述

Java反射机制:

  • 是指在运行时去获取一个类的变量和方法信息。
  • 然后通过获取的信息来创建对象,调用方法的一种机制。
  • 由于这种,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。
获取Class类的对象


案例:
  1. //Student类
  2. public class Student {
  3.     /**
  4.      * 成员变量:私有,默认,公共
  5.      */
  6.     private String name;
  7.     int age;
  8.     public String address;
  9.     //构造方法:一个私有,一个默认,两个公共
  10.     public Student() {
  11.     }
  12.     private Student(String name) {
  13.         this.name = name;
  14.     }
  15.     Student(String name, int age) {
  16.         this.name = name;
  17.         this.age = age;
  18.     }
  19.     public Student(String name, int age, String address) {
  20.         this.name = name;
  21.         this.age = age;
  22.         this.address = address;
  23.     }
  24.     /**
  25.      * 成员方法:一个私有,四个公共
  26.      */
  27.     private void function() {
  28.         System.out.println("function");
  29.     }
  30.     public void method1() {
  31.         System.out.println("method");
  32.     }
  33.     public void method2(String s) {
  34.         System.out.println("method:" + s);
  35.     }
  36.     public String method3(String s, int i) {
  37.         return s + "," + i;
  38.     }
  39.     @Override
  40.     public String toString() {
  41.         return "Student{" +
  42.                 "name='" + name + '\'' +
  43.                 ", age=" + age +
  44.                 ", address='" + address + '\'' +
  45.                 '}';
  46.     }
  47. }
复制代码
  1. public class Demo {
  2.     public static void main(String[] args) throws ClassNotFoundException {
  3.         //使用类的class属性获取该类对应的Class对象
  4.         Class<Student> c1 = Student.class;
  5.         System.out.println(c1);
  6.         //一个类在内存中只有一个字节码文件对象
  7.         Class<Student> c2 = Student.class;
  8.         System.out.println(c1 == c2);
  9.         System.out.println("-------------------");
  10.         /*通过调用对象的getClass()方法,返回对象所属类的class对象
  11.         该方法是Object类中的方法,所有的Java对象都可以调用该方法*/
  12.         Student stu = new Student();
  13.         Class<? extends Student> c3 = stu.getClass();
  14.         System.out.println(c1 == c3);
  15.         System.out.println("-------------------");
  16.         //使用Class类中的静态方法forName(String className),返回对象所属类的class对象
  17.         Class<?> c4 = Class.forName("com.fanshe.Student");
  18.         System.out.println(c1 == c4);
  19.     }
  20. }
复制代码
运行结果:
  1. class com.fanshe.Student
  2. true
  3. -------------------
  4. true
  5. -------------------
  6. true
复制代码
反射获取构造方法并使用



  • getConstructors():返回一个数组,包含该Class对象中的public公共构造函数
  • getDeclaredConstructors():返回一个数组,包含该Class对象中的所有构造函数
  • getConstructor(参数列表):获取指定的公共构造函数对象
  • getDeclaredConstructor(参数列表):获取指定的构造函数对象
  • newInstance(参数):构造方法创建对象
  • setAccessible(boolean flag):值为true时取消访问检查
练习:
  1. public class Demo2 {
  2.     public static void main(String[] args) throws Exception {
  3.         //获取Class对象
  4.         Class<?> c = Class.forName("com.fanshe.Student");
  5.         //getConstructors():返回一个数组,包含该Class对象中的public公共构造函数
  6.         Constructor<?>[] cons = c.getConstructors();
  7.         System.out.println("公共构造函数:");
  8.         for (Constructor<?> con : cons) {
  9.             System.out.println(con);
  10.         }
  11.         //getDeclaredConstructors():返回一个数组,包含该Class对象中的所有构造函数
  12.         Constructor<?>[] dCons = c.getDeclaredConstructors();
  13.         System.out.println("所有构造函数:");
  14.         for (Constructor<?> dCon : dCons) {
  15.             System.out.println(dCon);
  16.         }
  17.         System.out.println("指定的公共构造函数1:");
  18.         //getConstructor():返回指定的公共构造函数的对象
  19.         //参数:构造方法的参数 和 数据类型对应的字节码文件对象(Class对象)
  20.         Constructor<?> con = c.getConstructor();
  21.         //公共构造函数的对象使用newInstance()创建实例对象
  22.         //newInstance():构造方法创建对象
  23.         Object obj = con.newInstance();
  24.         System.out.println(obj);
  25.         System.out.println("指定的公共构造函数2:");
  26.         //基本数据类型 也可以通过.class 得到对应的Class类型
  27.         System.out.println(c.getConstructor(String.class, int.class, String.class).newInstance("李白",22,"西安"));
  28.         System.out.println("指定的构造函数");
  29.         //getDeclaredConstructor():获取指定的构造函数
  30.         //参数:构造方法的参数 和 数据类型对应的字节码文件对象(Class对象)
  31.         Constructor<?> dCon = c.getDeclaredConstructor(String.class);
  32.         //setAccessible():值为true时取消访问检查
  33.         dCon.setAccessible(true);
  34.         System.out.println(dCon.newInstance("杨玉环"));
  35.     }
  36. }
复制代码
运行结果:
  1. 公共构造函数:
  2. public com.fanshe.Student(java.lang.String,int,java.lang.String)
  3. public com.fanshe.Student()
  4. 所有构造函数:
  5. public com.fanshe.Student(java.lang.String,int,java.lang.String)
  6. com.fanshe.Student(java.lang.String,int)
  7. private com.fanshe.Student(java.lang.String)
  8. public com.fanshe.Student()
  9. 指定的公共构造函数1:
  10. Student{name='null', age=0, address='null'}
  11. 指定的公共构造函数2:
  12. Student{name='李白', age=22, address='西安'}
  13. 指定的构造函数
  14. Student{name='杨玉环', age=0, address='null'}
复制代码
反射获取成员变量并使用

Class类中用于获取成员变量的方法

  • getFields():获取公共的成员变量
  • getDeclaredFields():获取所有的成员变量
  • getField(成员变量):获取指定的公共成员变量
  • getDeclaredField(成员变量):获取指定的成员变量
Field类中,给成员变量赋值的方法

  • set(Object obj,Object value):给obj方法实例中的成员变量赋值
练习:
  1. public class Demo3 {
  2.     public static void main(String[] args) throws Exception {
  3.         //获取Class对象
  4.         Class<?> c = Class.forName("com.fanshe.Student");
  5.         //getFields():获取公共的成员变量
  6.         Field[] fields = c.getFields();
  7.         System.out.println("获取公共的成员变量:");
  8.         for (Field field : fields) {
  9.             System.out.println(field);
  10.         }
  11.         //getDeclaredFields():获取所有的成员变量
  12.         Field[] df = c.getDeclaredFields();
  13.         System.out.println("获取所有的成员变量:");
  14.         for (Field field : df) {
  15.             System.out.println(field);
  16.         }
  17.         System.out.println("获取指定的公共成员变量并赋值,再创建对象:");
  18.         //获取指定的公共成员变量
  19.         Field addressField = c.getField("address");
  20.         //获取指定的公共构造方法,并创建方法实例
  21.         Object obj = c.getConstructor().newInstance();
  22.         //给方法中的成员变量赋值
  23.         addressField.set(obj,"西安");
  24.         //输出方法实例(对象)
  25.         System.out.println(obj);
  26.         System.out.println("获取指定的公共构造函数对象,再实例化对象:");
  27.         //获取单个公共方法
  28.         Constructor<?> con = c.getConstructor();
  29.         //创建方法实例
  30.         Object obj1 = con.newInstance();
  31.         System.out.println(obj1);
  32.         System.out.println("获取指定的成员变量并赋值,再实例化对象:");
  33.         //获取指定的成员变量
  34.         Field nameField = c.getDeclaredField("name");
  35.         Field ageField = c.getDeclaredField("age");
  36.         Field addField = c.getDeclaredField("address");
  37.         //取消访问检查
  38.         nameField.setAccessible(true);
  39.         ageField.setAccessible(true);
  40.         addField.setAccessible(true);
  41.         //给成员变量赋值
  42.         nameField.set(obj1,"胡辣汤");
  43.         ageField.set(obj1,10);
  44.         addField.set(obj1,"北京");
  45.         //输出对象
  46.         System.out.println(obj1);
  47.     }
  48. }
复制代码
运行结果:
  1. 获取公共的成员变量:
  2. public java.lang.String com.fanshe.Student.address
  3. 获取所有的成员变量:
  4. private java.lang.String com.fanshe.Student.name
  5. int com.fanshe.Student.age
  6. public java.lang.String com.fanshe.Student.address
  7. 获取指定的公共成员变量并赋值,再创建对象:
  8. Student{name='null', age=0, address='西安'}
  9. 获取指定的公共构造函数对象,再实例化对象:
  10. Student{name='null', age=0, address='null'}
  11. 获取指定的成员变量并赋值,再实例化对象:
  12. Student{name='胡辣汤', age=10, address='北京'}
复制代码
反射获取成员方法并使用

Class类中用于获取成员方法的方法

  • getMethods():获取全部的公共成员方法数组,包含继承的方法
  • getDeclaredMethods():获取全部的成员方法数组,不包含继承的方法
  • getMethod("方法名",参数类型.class):获取单个公共成员方法对象
  • getDeclaredMethod("方法名",参数类型.class):获取单个成员方法对象
Method类中用于调用成员方法的方法

  • invoke(实体类对象,方法参数列表):调用实体类对象的成员方法
练习:
  1. public class Demo4 {
  2.     public static void main(String[] args) throws Exception {
  3.         //获取Class对象
  4.         Class<?> c = Class.forName("com.fanshe.Student");
  5.         System.out.println("获取全部的公共成员方法:");
  6.         //getMethods():获取全部的公共成员方法,包含继承的方法
  7.         Method[] methods = c.getMethods();
  8.         for (Method method : methods) {
  9.             System.out.println(method);
  10.         }
  11.         System.out.println("获取全部的成员方法:");
  12.         //getDeclaredMethods():获取全部的成员方法,不包含继承的方法
  13.         Method[] dms = c.getDeclaredMethods();
  14.         for (Method dm : dms) {
  15.             System.out.println(dm);
  16.         }
  17.         System.out.println("获取单个的公共成员方法1:");
  18.         //getMethod("方法名",参数类型.class):获取单个的公共成员方法对象
  19.         Method method1 = c.getMethod("method1");
  20.         //获取无参构造方法,创建实体类对象
  21.         Object obj1 = c.getConstructor().newInstance();
  22.         //invoke(实体类对象,方法参数列表):调用对象的成员方法
  23.         method1.invoke(obj1);
  24.         System.out.println("获取单个的公共成员方法2:");
  25.         Method method2 = c.getMethod("method2",String.class);
  26.         method2.invoke(obj1,"马超");
  27.         System.out.println("获取单个的公共成员方法3:");
  28.         Method method3 = c.getMethod("method3", String.class, int.class);
  29.         //有返回值,先接收一下
  30.         Object obj2 = method3.invoke(obj1, "赵云", 22);
  31.         //输出返回结果
  32.         System.out.println(obj2);
  33.         System.out.println("获取单个的成员方法:");
  34.         //getDeclaredMethod("方法名",参数类型):获取单个的成员方法对象
  35.         Method dm = c.getDeclaredMethod("function");
  36.         //取消访问检查
  37.         dm.setAccessible(true);
  38.         dm.invoke(obj1);
  39.     }
  40. }
复制代码
运行结果:
  1. 获取全部的公共成员方法:
  2. public java.lang.String com.fanshe.Student.toString()
  3. public void com.fanshe.Student.method1()
  4. public java.lang.String com.fanshe.Student.method3(java.lang.String,int)
  5. public void com.fanshe.Student.method2(java.lang.String)
  6. public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
  7. public final void java.lang.Object.wait() throws java.lang.InterruptedException
  8. public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
  9. public boolean java.lang.Object.equals(java.lang.Object)
  10. public native int java.lang.Object.hashCode()
  11. public final native java.lang.Class java.lang.Object.getClass()
  12. public final native void java.lang.Object.notify()
  13. public final native void java.lang.Object.notifyAll()
  14. 获取全部的成员方法:
  15. public java.lang.String com.fanshe.Student.toString()
  16. private void com.fanshe.Student.function()
  17. public void com.fanshe.Student.method1()
  18. public java.lang.String com.fanshe.Student.method3(java.lang.String,int)
  19. public void com.fanshe.Student.method2(java.lang.String)
  20. 获取单个的公共成员方法1:
  21. method
  22. 获取单个的公共成员方法2:
  23. method:马超
  24. 获取单个的公共成员方法3:
  25. 赵云,22
  26. 获取单个的成员方法:
  27. function
复制代码
反射练习-越过泛型检查

如何实现在ArrayList< Integer >集合中添加一个字符串数据?
  1. public class Demo5 {
  2.     public static void main(String[] args) throws Exception {
  3.         //创建集合
  4.         ArrayList<Integer> list = new ArrayList<>();
  5.         //添加数据
  6.         list.add(10);
  7.         list.add(20);
  8.         list.add(30);
  9.         //输出集合
  10.         System.out.println(list);
  11.         //利用反射,在list中添加一个String数据
  12.         Class<? extends ArrayList> lc = list.getClass();
  13.         Method ad = lc.getMethod("add", Object.class);
  14.         ad.invoke(list,"hello");
  15.         //输出添加String数据后的集合
  16.         System.out.println(list);
  17.     }
  18. }
复制代码
运行结果:
  1. [10, 20, 30]
  2. [10, 20, 30, hello]
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万有斥力

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表