Java高级-反射

2023-09-21 17:43:13

目录

认识反射、获取类

反射(Reflection)

反射可进行的操作

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

获取对象的三种方法

获取构造器对象并使用

获取构造器的方法

 获取构造器的作用

 获取成员变量和方法对象并使用

获取类的成员变量的方法

获取类的成员变量的作用

获取成员方法的方法

获取成员方法的作用


认识反射、获取类

反射(Reflection)

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

反射可进行的操作

加载类,获取类的字节码:Class对象
获取对象的三种方法
  • 反射第一步操作必须得到该类的Class对象
  • Class c1 = 类名.class
    • package com.example.Test;
      
      public class draft {
          public static void main(String[] args) {
              Class c1 = Student.class;
              // 打印输出全类名,即全限定名
              System.out.println(c1.getName());
              // 打印输出简类名,即类名
              System.out.println(c1.getSimpleName());
          }
      }
      
      class Student {
      
      };
    • 运行结果如下

  • 调用Class提供方法:public static Class forname(String package);
    • package com.example.Test;
      
      public class draft {
          public static void main(String[] args) throws Exception {
              Class c2 = Class.forName("com.example.Test.Student");
              System.out.println(c2.getName());
              System.out.println(c2.getSimpleName());
      
          }
      }
      
      class Student {
      
      };
    • 运行结果如下

  • Object提供的方法:public Class getClass(); Class c3 = 对象.getClass();
    • package com.example.Test;
      
      public class draft {
          public static void main(String[] args) throws Exception {
              Student s = new Student();
              Class c = s.getClass();
              System.out.println(c.getName());
              System.out.println(c.getSimpleName());
      
          }
      }
      
      class Student {
      
      };
    • 运行结果如下


获取构造器对象并使用
获取构造器的方法
  • 构造器就是构造方法
  • 方法名描述
    public Constructor<T> getConstructor(Class<?>... parameterTypes)获取具有指定参数类型的公共(public修饰)构造器。
    public Constructor<?>[] getConstructors()获取所有公共(public修饰)构造器的数组。
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)获取具有指定参数类型的构造器,包括私有构造器。
    public Constructor<?>[] getDeclaredConstructors()获取所有构造器的数组,包括私有构造器。

     
  • 只演示一种
    • 具体代码如下
      • package com.example.Test;
        
        import org.junit.Test;
        
        import java.lang.reflect.Constructor;
        
        public class draft {
            @Test
            public static void main(String[] args) throws Exception {
                // 1. 反射第一步 获取该类的Class对象
                Class c = Student.class;
                // 2. todo 获取该类的全部构造器
                Constructor[] constructors = c.getConstructors();
                // 3.遍历数组中的构造器
                for (Constructor constructor : constructors) {
                    System.out.println(constructor.getName() + "参数个数为:" + constructor.getParameterCount());
                }
                System.out.println("----------------");
                // todo 根据参数类型获取构造器
                Constructor constructor1 = c.getConstructor(String.class, Integer.class);
                System.out.println(constructor1.getName() + "参数个数为:" + constructor1.getParameterCount());
        
            }
        }
        
        class Student {
            private String name;
            private Integer age;
        
            // todo 无参构造方法
            public Student() {
            }
        
            // todo 全参构造方法
            public Student(String name, Integer age) {
                this.name = name;
                this.age = age;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public Integer getAge() {
                return age;
            }
        
            public void setAge(Integer age) {
                this.age = age;
            }
        };
    • 运行结果如下

 获取构造器的作用
  • 初始化对象返回
  • 构造器提供的方法
  • 方法名描述
    public T newInstance(Object... initargs)使用构造器创建一个新的对象实例。initargs参数是构造器的参数列表,用于传递初始化数据。该方法会调用构造器并返回新创建的对象实例。
    public void setAccessible(boolean flag)设置构造器的可访问性。如果flag为true,则可以访问私有构造器(暴力反射);如果flag为false,则无法访问私有构造器。
  • 具体代码如下
    • package com.example.Test;
      
      import org.junit.Test;
      
      import java.lang.reflect.Constructor;
      
      public class draft {
          @Test
          public static void main(String[] args) throws Exception {
              // 1. 反射第一步 获取该类的Class对象
              Class c = Student.class;
              // todo 根据参数类型获取构造器
              Constructor constructor1 = c.getConstructor(String.class, Integer.class);
              System.out.println(constructor1.getName() + "参数个数为:" + constructor1.getParameterCount());
              Student s1 = (Student) constructor1.newInstance("hkm", 20); // todo 根据参数调用对应的构造器
              System.out.println(s1.toString());
              System.out.println("-------------------------------");
              Constructor constructor2 = c.getConstructor();
              System.out.println(constructor2.getName() + "参数个数为:" + constructor2.getParameterCount());
              Student s2 = (Student) constructor2.newInstance(); // todo 根据参数调用对应的构造器
              System.out.println(s2.toString());
      
          }
      }
      
      class Student {
          private String name;
          private Integer age;
      
          // todo 无参构造方法
          public Student() {
              System.out.println("无参构造器执行了~~");
          }
      
          // todo 全参构造方法
          public Student(String name, Integer age) {
              this.name = name;
              this.age = age;
              System.out.println("全参构造器执行了~~~");
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Integer getAge() {
              return age;
          }
      
          public void setAge(Integer age) {
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      };
  • 运行结果如下


 获取成员变量和方法对象并使用
  • 获取类的成员变量的方法
    • Class提供的从类中获取成员变量的方法
    • 方法名描述
      public Field getField(String name)根据成员变量的名称获取公共的成员变量。只能获取到公共的成员变量,不能获取到私有的成员变量。如果指定名称的成员变量不存在,或者指定名称的成员变量不是公共的,则会抛出NoSuchFieldException异常。
      public Field[] getFields()获取所有公共(public修饰的)的成员变量。返回一个Field对象数组,包含了所有公共的成员变量。
      public Field getDeclaredField(String name)根据成员变量的名称获取指定的成员变量,包括私有的成员变量。如果指定名称的成员变量不存在,或者指定名称的成员变量不是当前类的成员变量,则会抛出NoSuchFieldException异常。
      public Field[] getDeclaredFields()获取所有的成员变量,包括公共的和私有的。返回一个Field对象数组,包含了所有的成员变量。
    • 具体代码
      • package com.example.Test;
        
        import org.junit.Test;
        
        import java.lang.reflect.Constructor;
        import java.lang.reflect.Field;
        
        public class draft {
            @Test
            public static void main(String[] args) throws Exception {
                // 1. 反射第一步 获取该类的Class对象
                Class c = Student.class;
                // todo 获取类中的全部成员变量
                Field[] fields = c.getDeclaredFields();
                for (Field field : fields) {
                    System.out.println(field.getName());
        
                }
                System.out.println("------------------");
                // todo 通过名称获取某个成员变量
                Field name = c.getDeclaredField("name");
                System.out.println(name.getName());
            }
        }
        
        class Student {
            private String name;
            private Integer age;
        
            // todo 无参构造方法
            public Student() {
                System.out.println("无参构造器执行了~~");
            }
        
            // todo 全参构造方法
            public Student(String name, Integer age) {
                this.name = name;
                this.age = age;
                System.out.println("全参构造器执行了~~~");
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public Integer getAge() {
                return age;
            }
        
            public void setAge(Integer age) {
                this.age = age;
            }
        
            @Override
            public String toString() {
                return "Student{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        '}';
            }
        };
    • 运行结果


      •  

  • 获取类的成员变量的作用
    • 赋值、取值

    • 赋值取值的方法

      • 方法

        说明

        void set(Object obj,value)赋值(为指定对象的成员变量赋值)
        void get(Object obj)取值(取出指定对象的成员变量的值)
        public void setAccessiable(boolean flag)设置为true,表示禁止访问控制(暴力反射
    • 具体代码如下

      • package com.example.Test;
        
        import org.junit.Test;
        
        import javax.swing.plaf.synth.SynthUI;
        import java.lang.reflect.Constructor;
        import java.lang.reflect.Field;
        
        public class draft {
            @Test
            public static void main(String[] args) throws Exception {
                // 1. 反射第一步 获取该类的Class对象
                Class c = Student.class;
                // todo 获取类中的全部成员变量
                Field[] fields = c.getDeclaredFields();
                for (Field field : fields) {
                    System.out.println(field.getName());
        
                }
                System.out.println("------------------");
                // todo 通过名称获取某个成员变量
                Field name = c.getDeclaredField("name");
        
                // todo 创建要赋值以及取值的类的对象
                Student student = new Student();
                name.set(student, "发老爷爷");
                System.out.println(student); // 赋值成功
                System.out.println(name.get(student));
        
                // todo 上述代码是对指定类Student中的name成员变量进行操作
        
                // todo 以下是对Student类中的age成员变量进行操作
                Field age = c.getDeclaredField("age");
                // 赋值
                age.set(student, 31);
                System.out.println(student);
                System.out.println(age.get(student));
                System.out.println("Student类中的age成员变量的赋值为"+ age.get(student));
            }
        }
        
        class Student {
            public String name;
            public Integer age;
        
            // todo 无参构造方法
            public Student() {
                System.out.println("无参构造器执行了~~");
            }
        
            // todo 全参构造方法
            public Student(String name, Integer age) {
                this.name = name;
                this.age = age;
                System.out.println("全参构造器执行了~~~");
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public Integer getAge() {
                return age;
            }
        
            public void setAge(Integer age) {
                this.age = age;
            }
        
            @Override
            public String toString() {
                return "Student{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        '}';
            }
        };
    • 运行结果如下


获取成员方法的方法
  • 方法说明
    getDeclaredMethods()返回类中声明的所有方法,包括公共、保护、默认(包)访问和私有方法。
    getMethods()返回类中所有公共方法,包括从父类继承的方法。
    getDeclaredMethod(String name, Class<?>... parameterTypes)返回类中指定名称和参数类型的方法。
    getMethod(String name, Class<?>... parameterTypes)返回类中指定名称和参数类型的公共方法,包括从父类继承的方法。
  • 具体代码如下
    • package com.example.Test;
      
      import org.junit.Test;
      
      import java.lang.reflect.Method;
      
      public class draft {
          @Test
          public static void main(String[] args) throws Exception {
              // 1. 反射第一步 获取该类的Class对象
              Class c = Student.class;
      //        todo 获取全部成员方法
              Method[] methods = c.getDeclaredMethods();
              for (Method method : methods) {
                  System.out.println(method.getName());
              }
              System.out.println("------------------------------------");
              // todo 获取某个成员方法
              Method student = c.getDeclaredMethod("run");
              System.out.println(student.getName());
          }
      
      }
      
      
      class Student {
          public String name;
          public Integer age;
      
          public void run() {
              System.out.println("run~~~~");
          }
      
          private void jump() {
              System.out.println("jump~~~");
          }
      
          // todo 无参构造方法
          public Student() {
              System.out.println("无参构造器执行了~~");
          }
      
          // todo 全参构造方法
          public Student(String name, Integer age) {
              this.name = name;
              this.age = age;
              System.out.println("全参构造器执行了~~~");
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Integer getAge() {
              return age;
          }
      
          public void setAge(Integer age) {
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      };

  • 运行结果如下
获取成员方法的作用
  • 依然是执行该方法
  • 方法说明
    public Object invoke(Object obj,Object ...args)触发某个对象的该方法执行
    public void setAccessible(boolean flag)设置为true,表示禁止访问控制(暴力反射)
  • 具体代码如下
    • package com.example.Test;
      
      import org.junit.Test;
      
      import java.lang.reflect.Method;
      
      public class draft {
          @Test
          public static void main(String[] args) throws Exception {
              // 1. 反射第一步 获取该类的Class对象
              Class c = Student.class;
      //        todo 获取全部成员方法
              Method[] methods = c.getDeclaredMethods();
              for (Method method : methods) {
                  System.out.println(method.getName());
              }
              System.out.println("------------------------------------");
              // todo 获取某个成员方法
              Method run = c.getDeclaredMethod("run");
              Method jump = c.getDeclaredMethod("jump", String.class);
              jump.setAccessible(true);
              Student student = new Student();
              jump.invoke(student, "hkm");
              run.invoke(student);
      
          }
      
      }
      
      
      class Student {
          public String name;
          public Integer age;
      
          public void run() {
              System.out.println("run~~~~");
          }
      
          private void jump(String name) {
              System.out.println(name + ":jump~~~");
          }
      
          // todo 无参构造方法
          public Student() {
              System.out.println("无参构造器执行了~~");
          }
      
          // todo 全参构造方法
          public Student(String name, Integer age) {
              this.name = name;
              this.age = age;
              System.out.println("全参构造器执行了~~~");
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Integer getAge() {
              return age;
          }
      
          public void setAge(Integer age) {
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      };
  • 运行结果如下

更多推荐

rabbitmq 面试题

1.交换机类型RabbitMQ是一个开源的消息队列系统,它支持多种交换机类型,用于在消息的生产者和消费者之间路由和分发消息DirectExchange(直接交换机):Direct交换机是最简单的交换机类型之一。它将消息按照消息的RoutingKey(路由键)与绑定的队列的RoutingKey进行精确匹配,并将消息发送到

一键自助建站系统源码带安装教程 傻瓜式部署搭建,让您的建站更高效

在这个数字时代,网站已成为企业或个人展示形象、推广业务的重要工具。为了满足这一需求,许多自助建站系统应运而生,大大降低了用户建站的门槛。给大家分享一款傻瓜式部署搭建的一键自助建站系统源码,让您轻松拥有高效建站能力。一、一键自助建站系统源码介绍这款一键自助建站系统源码具有以下特点:简单易用:用户只需通过简单的鼠标点击和输

Golang Gorm 一对多 关联模式 Association + Find 查询关联

查找关联//User拥有并属于多种language,`user_languages`是连接表typeUserstruct{gorm.ModelLanguages[]Language`gorm:"many2many:user_languages;"`}typeLanguagestruct{gorm.ModelNamest

I Pa?sWorD

2023icpc网络赛第一场I题意:题目给出只包含大小写字母,数字以及'?'的字符串,对于每一个小写字母,这一位字符既有可能是该小写字母,也有可能是该小写字母的对应大写字母,也就是该位的字符有两种可能,对于问号,可能是所有大写字母或者所有小写字母,或者所有单数字,则共有62种情况,而对于大写字母和数字位则都是确定的只有

Hive【非交互式使用、三种参数配置方式】

前言今天开始学习Hive,因为毕竟但凡做个项目基本就避不开用Hive,争取这学期结束前做个小点的项目。第一篇博客内容还是比较少的,环境的搭建配置太琐碎没有写。Hive常用使用技巧交互式使用就是我们正常的进入hive命令行下的使用模式。非交互式使用所谓非交互式,也就是不需要进入hive命令行,直接在我们linuxShel

STViT-R 代码阅读记录

目录一、SwinTransformer1、原理2、代码二、STViT-R1、中心思想2、代码与原文本次不做具体的训练。只是看代码。所以只需搭建它的网络,执行一次前向传播即可。一、SwinTransformer1、原理主要思想,将token按区域划分成窗口,只需每个窗口内的token单独进行self-attention。

Mybatis sql参数自动填充

问题描述在日常开发中,经常会遇到Mybatissql语句的操作问题,由于Mybatis实现sql的动态拼接,开发过程中,为了验证sql是否书写正确,通常需要获取的控制台打印的sql语句来检查是否拼接正确。如下图所示:那么为了验证sql的正确性,需要复制控制台sql以及sql参数,手工进行拼接后在数据库连接工具(比如na

python学习--字符串的常用操作

字符串查询操作功能方法名称作用查询方法index()查找子串substr第一次出现的位置,如果查找的子串不存在时,则抛出valueError查询方法rindex()查找子串sunstr最后一次出现的位置,如果查找的子串不存在时,则抛出valueError查询方法find()查找子串sunstr第一次出现的位置,如果查找

DGUS 功能升级:任意页面控件均可灵活叠加

针对进一步提升DGUS平台控件组合灵活度的市场需求,迪文在DGUS平台中新增设了“页面叠加开关”接口,可用于实现全局动态报警提示等功能。使用该功能,用户可以将任意页面的控件叠加到全部剩余页面上,叠加页面的控件默认为最高优先级,叠加页面上的控件处于被叠加页面的最上层(包含叠加页面的全部显示控件和触摸控件)。触摸控件的优先

spring security教程(一)--认证

零.简介【1】简介【2】登录校验流程【3】原理(入门的时候先了解一下就好)一.思路分析二.建表确保你已经建立好一张用户表,并且引入springboot,mybatis,mp,slf4j等基础依赖。即使你有多个角色你也可以将他们的相同信息(如用户名密码登都提取到一张表中)。并根据表编写对应实体类和mapper。上面是我建

【SpringMVC】JSON数据传输与异常处理的使用

文章目录一、Jackson1.1Jackson是什么1.2常用注解1.3实例1.3.1导入依赖1.3.2配置spring-mvc.xml1.3.3JsonController.java二、SpringMVC异常处理机制2.1使用原因2.2SpringMVC异常处理2.2.1异常处理机制流程图2.2.2异常处理的三种方式

热文推荐