Java反射

反射

反射(Reflection)

  • 反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。

如何获取某个类的信息?

  • 加载类,获取类的字节码:Class对象

    获取Class对象的三种方式:

    1. Class c1 = 类名.class
    2. 调用Class提供的方法:public static Class forName(String package);
    3. Object提供的方法:public Class getClass; Class c3 = 对象.getClass();
  • 获取类的构造器:Construtor对象

    • 方法说明
      Constructor<?>[] getConstructors()获取全部构造器(只能获取public修饰的)
      Constructor<?>[] getDeclaredConstructors()获取全部构造器(只要存在就能拿到)
      Constructor getConstructor(Class<?>… parameterTypes)获取某个构造器(只能获取public修饰的)
      Constructor getDeclaredConstructor(Class<?>… parameterTypes)获取某个构造器(只要存在就能拿到)

      获取类构造器的作用:初始化对象并返回

      Construtor提供的方法说明
      T newInstance(Object… initargs)调用次构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
      public void setAccessible(boolean flag)设置为true,表示禁止检查访问控制(暴力反射)
  • 获取类的成员变量:Field对象

    • 方法说明
      public Field[] getFields()获取类的全部成员变量(只能获取public修饰的)
      public Field[] getDeclaredFields()获取类的全部成员变量(只要存在就能拿到)
      public Field getField(String name)获取类的某个成员变量(只能获取public 修饰的)
      public Field getDeclaredField(String name)获取类的某个成员变量(只要存在就能拿到)

      对获取到的成员变量进行赋值和取值

      方法说明
      void set(Object obj,Object value)赋值
      Object get(Object obj)取值
      public void setAccessible(boolean flag)设置为true,表示禁止检查访问控制(暴力反射)
  • 获取类的成员方法:Methond对象

    • 方法说明
      Method[] getMethods()获取类的全部成员方法(只能获取public修饰的)
      Method[] getDeclaredMethods()获取类的全部成员方法(只要存在就能拿到)
      Method getMethod(String name,Class<?>… parameterTypes)获取类的的某个成员方法(只能获取public修饰的)
      Method getDeclaredMethod(String name,Class<?>… paraterTypes)获取类的某个成员方法(只要存在就能拿到)

      执行成员方法

      Method提供的方法说明
      public Object invoke(Object obj,Object… args)触发某个对象的该方法执行
      public void setAccessible(boolean flag)设置为true,表示禁止检查访问控制(暴力反射)

      示例代码:

      package reflect;
      
      public class Student {
          public int age;
          private String name;
      
          public Student() {
              System.out.println("无参数构造器");
          }
      
          public Student(int age) {
              this.age = age;
              System.out.println("public 有参数构造器");
          }
      
          private Student(String name) {
              this.name = name;
              System.out.println("private 有参数构造器");
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public void study(){
              System.out.println("我爱学习");
          }
      
          public void study(String name){
              System.out.println(name + "爱学习");
          }
      
          private void play(){
              System.out.println("我爱打游戏");
          }
      }
      
      package reflect;
      
      import java.lang.reflect.Constructor;
      import java.lang.reflect.Field;
      import java.lang.reflect.Method;
      
      public class TestClass {
          public static void main(String[] args) throws Exception {
              System.out.println("--------获取类的字节码文件--------------");
              //方式一
              Class c1 = Student.class;
              System.out.println(c1.getName()); //全类名
              System.out.println(c1.getSimpleName());//简名 Student
      
              //方式二
              Class c2 = Class.forName("reflect.Student"); //参数是全限定名
              System.out.println(c2.getName());
      
              //方式三
              Student s1 = new Student();
              Class c3 = s1.getClass();
      
              //三种方式取得的都是同一个Class对象
              System.out.println(c1 == c2);
              System.out.println(c1 == c3);
      
              System.out.println("-------------------获取类的构造器------------------------");
              //只能获取public所有的构造器
              Constructor[] constructors = c1.getConstructors();
              for (int i = 0; i < constructors.length; i++) {
                  System.out.println(constructors[i].getName() + " --->" + constructors[i].getParameterCount());
              }
              //可以获取所有的构造器
              Constructor[] constructors2 = c1.getDeclaredConstructors();
              for (int i = 0; i < constructors2.length; i++) {
                  System.out.println(constructors2[i].getName() + " --->" + constructors2[i].getParameterCount());
              }
      
              //获取某个public 构造器
              Constructor constructors3 = c1.getConstructor();
              System.out.println(constructors3.getName() + " --->" + constructors3.getParameterCount());
      
              //获取某个任意一个有参数的构造器,参数就是构造器的参数类型.class
              Constructor constructors4 = c1.getDeclaredConstructor(String.class);
              System.out.println(constructors4.getName() + " --->" + constructors4.getParameterCount());
      
              System.out.println("----------------使用构造器初始化对象并返回-----------------------");
              //禁止访问检查,即使是private构造器,在外面也可以调用
              constructors4.setAccessible(true);
              Student s = (Student) constructors4.newInstance("zxx");
      
              System.out.println("-------------------获取类的成员变量------------------");
              Field[] field = c1.getFields();
              for (int i = 0; i < field.length; i++) {
                  System.out.println(field[i].getName() + " " + field[i].getType());
              }
      
              Field[] field2 = c1.getDeclaredFields();
              for (int i = 0; i < field2.length; i++) {
                  System.out.println(field2[i].getName() + " " + field2[i].getType());
              }
      
              Field fage = c1.getField("age");
              System.out.println(fage.getName() + " " + fage.getType());
      
              Field fname = c1.getDeclaredField("name");
              System.out.println(fname.getName() + " " + fname.getType());
      
              System.out.println("------------------------对成员变量进行赋值和取值--------------------------------");
              Student student = new Student();
              //对某个对象进行赋值
              fage.set(student, 5);
              //对某个对象进行取值
              System.out.println(fage.get(student));
      
              System.out.println("----------------------从类中获取成员方法-----------------------------------------");
              Method[] methods = c1.getMethods();
              for (Method method : methods) {
                  System.out.println(method.getName() + "--" + method.getParameterCount() + "--" + method.getParameterTypes());
              }
              System.out.println("--------------------");
              Method[] methods2 = c1.getDeclaredMethods();
              for (Method method : methods2) {
                  System.out.println(method.getName() + "--" + method.getParameterCount() + "--" + method.getParameterTypes());
              }
      
              //无参
              Method m1 = c1.getMethod("study");
              System.out.println(m1.getName());
              //有参
              Method m2 = c1.getMethod("study", String.class);
              System.out.println(m2.getName());
      
              //私有方法
              Method m3 = c1.getDeclaredMethod("play");
              System.out.println(m3.getName());
      
              System.out.println("---------------------------------调用类中的成员方法----------------------------------------");
              // 无参的study方法,无返回值res = null
              Object res = m1.invoke(student);
              // 有参的study方法
              m2.invoke(student, "zxx");
              // private方法
              m3.setAccessible(true);
              m3.invoke(student);
          }
      }
      

反射的作用和应用场景

  • 基本作用:可以得到一个类中的全部成分然后进行操作
  • 可以破坏封装性
  • 适合做Java的框架

使用反射做一个简易版的框架

​ 需求:对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去

​ 实现步骤:

  1. 定义一个方法,可以接受任意对象
  2. 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员信息
  3. 遍历成员列表,然后提取成员变量在该对象中的具体值
  4. 把成员变量名、对应的值,写到文件中去
package reflect;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class SimpleFrame {
    public static void getFieldsAndValue(Object obj) throws IllegalAccessException, FileNotFoundException {
        PrintStream printStream = new PrintStream(new FileOutputStream(new File("D:\\javaCode\\ReflectStudy\\src\\demo.txt")), true);
        //  obj是任意对象
        Class c1 = obj.getClass();
        String cname = c1.getName();
        printStream.println("---------------" + cname + "-------------------");
        //  2.从这个类中获取全部成员变量
        Field[] fields = c1.getDeclaredFields();
        //  3.遍历成员变量
        for (Field field : fields) {
            // 4.拿到成员变量的名字
            String fieldName = field.getName();
            field.setAccessible(true);
            String fieldValue =  field.get(obj) + "";
            printStream.println(fieldName + "->" + fieldValue);
        }
        printStream.close();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迪迦敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值