当前位置: 首页 > news >正文

Java 反射

一. 概述

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

二. 获取类的字节码:Class对象

        三种方式:

        1. Class c1 =  类名.class:

        2. 调用Class提供的方法:public static Class forName(String package)

        3. Object提供的方法:public Class getClass(); Calss3 = 对象.getClass()

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}



public static void main(String[] args) throws ClassNotFoundException {
        Class c = Student.class;
        System.out.println(c.getName());//全类名
        System.out.println(c.getSimpleName());//简名 Student

        Class c2 = Class.forName( "com.wyyzs.d01.Student");
        System.out.println(c2.getName());
        System.out.println(c2.getSimpleName());

        Student student = new Student();
        Class c3 = student.getClass();
        System.out.println(c3.getName());
        System.out.println(c3.getSimpleName());

}

三. 获取类的构造器

        获取类的构造器

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

        获取类构造器的作用

                初始化对象返回

Constructor提供的方法

说明
T newInstance(Object... initargs)调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
public void setAccessible(boolean flag)设置true,表示禁止检查访问控制(暴力反射)
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}



@Test
    public void test1() throws Exception {
        Class studentClass = Student.class;

        //Constructor<?>[] getConstructors()	获取全部构造器(只能获取public 修饰的)
        Constructor[] constructors = studentClass.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println(constructor.getName() + " " + constructor.getParameterTypes().length);
        }
        System.out.println("------------------------");

        //Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
        Constructor[] constructors2 = studentClass.getDeclaredConstructors();
        for(Constructor constructor : constructors2){
            System.out.println(constructor.getName() + " " + constructor.getParameterTypes().length);
        }
        System.out.println("------------------------");

        //Constructor<?>[] getConstructor(Class<?>... parameterTypes) 	获取某个构造器(只能获取public修饰的)
        //无参
        Constructor constructors3 = studentClass.getConstructor();
        System.out.println(constructors3.getName() + " " + constructors3.getParameterTypes().length);
        //有参
        Constructor constructors4 = studentClass.getConstructor(String.class, int.class);
        System.out.println(constructors4.getName() + " " + constructors4.getParameterTypes().length);

        System.out.println("------------------------");
        //Constructor<?>[] getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)
        //无参
        Constructor constructors5 = studentClass.getDeclaredConstructor();
        System.out.println(constructors5.getName() + " " + constructors5.getParameterTypes().length);
        //有参
        Constructor constructors6 = studentClass.getDeclaredConstructor(String.class);
        System.out.println(constructors6.getName() + " " + constructors6.getParameterTypes().length);
        Constructor constructors7 = studentClass.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructors7.getName() + " " + constructors7.getParameterTypes().length);



        //T newInstance(Object... initargs)	调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
        //public void setAccessible(boolean flag)	设置true,表示禁止检查访问控制(暴力反射)

        //调 constructors6 私有构造器 会报权限异常 此时 使用 setAccessible 设置true,表示禁止检查访问控制(暴力反射)

       /* Student student = (Student) constructors6.newInstance();
        System.out.println(student);*/

        constructors6.setAccessible(true);
        Student student2 = (Student) constructors6.newInstance("卡莎");
        System.out.println(student2);

       Student student3 = (Student) constructors7.newInstance("卡莎", 18);
        System.out.println(student3);
    }

四. 获取类的成员变量

        从类中获取成员变量的方法

Class提供了从类中获取成员变量的方法说明
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)设置为ture,表示禁止检查访问控制
public class Dog {
    private String name;
    private int age;
    public static int o;
    public static  final String C = "狗狗";


    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

 @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}



 @Test
   public void Test3_Field() throws NoSuchFieldException {
        //获取类的成员变量


        //得到类的Class对象
        Class dog = Dog.class;

        //public Field[] getFields()	获取类全部的成员变量(只能获取public修饰的)
        Field[] fields = dog.getFields();
        for(Field f : fields){
            System.out.println(f.getName() + "---->" + f.getType());
        }
        System.out.println("-------------------------------------");
        //public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
        Field[] fields1 = dog.getDeclaredFields();
        for(Field f : fields1){
            System.out.println(f.getName() + "---->" + f.getType());
        }

        System.out.println("-------------------------------------");
        //public Field getField(String name)	获取类的某个成员变量(只能获取public修饰的)
        Field field = dog.getField("o");
        System.out.println(field.getName() + "---->" + field.getType());
        Field field2 = dog.getField("C");
        System.out.println(field2.getName() + "---->" + field2.getType());
        System.out.println("-------------------------------------");
        //public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能获取)
        Field field3 = dog.getDeclaredField("name");
        System.out.println(field3.getName() + "---->" + field3.getType());
        Field field4 = dog.getDeclaredField("age");
        System.out.println(field4.getName() + "---->" + field4.getType());

        System.out.println("===================================");

        //void set(Object obj, Object value)	赋值
        Dog dog1 = new Dog();
        //field3->name 为私有 赋值会抛异常 需要 void setAccessible(boolean flag) 设置为ture,表示禁止检查访问控制

        //public void setAccessible(boolean flag)	设置为ture,表示禁止检查访问控制
        field3.setAccessible(true);
        field3.set(dog1, "拉布拉多");
        System.out.println(dog1);


        //Object get(Object obj)	取值
        //field3->name
        String name = (String) field3.get(dog1);
        System.out.println(name);
    }

五. 获取类的成员方法 

        从类中获取成员方法

Class提供了从类中获取成员方法说明
Method[] getMethods()获取类的全部成员方法(只能获取public 修饰的) 使用较少
Method[] getDeclaredMethods()获取类的全部成员方法(只要存在就能拿到)
Method getMethod(String name, Class<?> parameterTypes)获取类的某个成员方法(只能获取public修饰的)
Method getDeclaredMethod(String name, Class<?> parameterTypes)获取类的某个成员方法(只要存在就能拿到)

        获取成员方法的作用

                获取成员方法的作用是执行该方法

Method提供的方法说明
public Object invoke(Object obj, Object... args)执行某个对象的该方法
public void setAccessible(boolean flag)设置为ture,表示禁止检查访问控制
public class Dog {
    private String name;
    private int age;
    public static int o;
    public static  final String C = "狗狗";


    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String eat(String food) {
        return "吃" + food + "吃的贼多";
    }

    public void run() {
        System.out.println("跑的贼快");
    }

    private void sleep() {
        System.out.println("睡得贼香");
    }

}


 @Test
    public void testGetMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class d = Dog.class;

        //Method[] getMethods()	获取类的全部成员方法(只能获取public 修饰的) 使用较少
        Method[] methods = d.getMethods();
        for(Method m : methods){
            System.out.println(m.getName() + "-->" + m.getParameterTypes().length);
        }
        System.out.println("-------------------");
        //Method[] getDeclaredMethods()	获取类的全部成员方法(只要存在就能拿到)
        Method[] methods2 = d.getDeclaredMethods();
        for(Method m : methods2){
            System.out.println(m.getName() + "-->" + m.getParameterTypes().length);
        }

        System.out.println("-------------------");
        //Method getMethod(String name, Class<?> parameterTypes)	获取类的某个成员方法(只能获取public修饰的)
        Method method = d.getMethod("eat", String.class);
        System.out.println(method.getName() + "-->" + method.getReturnType());

        //Method getDeclaredMethod(String name, Class<?> parameterTypes)	获取类的某个成员方法(只要存在就能拿到)
        Method method2 = d.getDeclaredMethod("sleep");
        System.out.println(method2.getName() + "-->" + method2.getReturnType());

        System.out.println("====================");
        //public Object invoke(Object obj, Object... args)	执行某个对象的该方法
        Dog dog = new Dog();
        //method为 public 可直接调用
        String s = (String) method.invoke(dog, "王中王");
        System.out.println(s);

        //method2->sleep为private 直接执行会报错 需要 void setAccessible(boolean flag)	设置为ture,表示禁止检查访问控制
        //public void setAccessible(boolean flag)	设置为ture,表示禁止检查访问控制
        method2.setAccessible(true);
        method2.invoke(dog);

    }

六. 反射的作用、应用场景

        作用

                1. 基本作用:可以得到一个类的全部成分然后进行操作。

                2. 可以破坏封装性

                3. 最重要的用途:适合做Java框架,主流的框架都会基于反射设计出一些通用的功能

        简易版框架

                实现步骤:

                1. 定义一个方法,可以接收任意对象

                2. 没收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量

                3. 变量成员变量,然后提取成员变量在该对象中的具体值

                4. 把成员变量名和值写到文件中

public class Student {
    private String name;
    private int age;
    private String gender;
    private String grade;

    public Student() {
    }

    public Student(String name, int age, String gender, String grade) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.grade = grade;
    }
}


public class Teacher {
    private String name;
    private int age;
    private String subject;

    public Teacher() {
    }

    public Teacher(String name, int age, String subject) {
        this.name = name;
        this.age = age;
        this.subject = subject;
    }
}


 @Test
    public void testA() throws Exception {
        Student s1 = new Student("卡莎", 18, "女", "99.8");
        Teacher teacher = new Teacher("张飞", 25, "语文");

        ObjectFrame.saveObject(s1);
        ObjectFrame.saveObject(teacher);

    }

相关文章:

  • docker 部署JAR
  • ES10中Object.fromEntries(),trimStart() ,trimend()的使用方法和使用场景例子
  • 三、linux字符驱动详解
  • 算法——位运算
  • 零基础学QT、C++(三)魔改QT组件库(付源码)
  • 第42天:Web开发-JavaEE应用Servlet技术路由配置生命周期过滤器Filter监听器Listen
  • C#```
  • Server-Sent Events(SSE)协议详解
  • 千峰React:组件使用(1)
  • 基于Spring Boot的售楼管理系统设计与实现(LW+源码+讲解)
  • Spring Cloud中如何使用Eureka:超详细指南
  • 产业园区数字孪生规划方案(40页PPT)
  • 嵌入式学习(18)---Linux文件编程中的进程
  • 代码随想录算法训练营第六天| 242.有效的字母异位词 、349. 两个数组的交集、202. 快乐数 、1. 两数之和
  • 《Kettle保姆级教学-性能调优,抽取速率提升800%》
  • java网络编程02 - HTTP、HTTPS详解
  • 若依-@Excel新增注解numberFormat
  • 【SFRA】笔记
  • 【可实战】Linux 常用统计命令:排序sort、去重uniq、统计wc
  • idea连接gitee完整教程
  • 纪念|“补白大王”郑逸梅,从藏扇看其眼光品味
  • 人民日报评论:莫让“胖东来们”陷入“棒杀”“捧杀”泥潭
  • 言短意长|党政主官如何塑造流量城市?
  • 繁荣活跃!“五一”假期全国重点零售和餐饮企业销售额同比增长6.3%
  • 美权威人士批“特朗普对进口电影征关税”:将杀死美电影产业
  • 建邦高科赴港上市,大股东陈子淳系山东建邦集团董事长陈箭之子