Java中的反射

  1. 类加载器

(1)类的加载

当我们的程序在运行后,第一次使用某个类的时候,会将此类的class文件读取到内存,并将此类

的所有信息存储到一个Class对象中。

说明:

a.图中的Class对象是指:java.lang.Class类的对象,此类由Java类库提供,专门用于存储类的信息。

b.我们程序中可以通过:"类名.class",或者"对象.getClass()"方法获取这个Class对象

(2)类的加载时机

a.创建类的实例。

b.调用类的静态变量,或者为静态变量赋值。

c.调用类的静态方法。

d.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。

e.初始化某个类的子类。

f.直接使用java.exe命令来运行某个主类。

以上六种情况的任何一种,都可以导致JVM将一个类加载到方法区。

(3)类加载器

类加载器:是负责将磁盘上的某个class文件读取到内存并生成Class的对象。

Java中有三种类加载器,它们分别用于加载不同种类的class:

a.启动类加载器(Bootstrap ClassLoader):用于加载系统类库<JAVA_HOME>\bin目录下的class,例如:rt.jar。

b.扩展类加载器(Extension ClassLoader):用于加载扩展类库<JAVA_HOME>\lib\ext目录下的class。

c.应用程序类加载器(Application ClassLoader):用于加载我们自定义类的加载器。

public class Test{ public static void main(String[] args) {
    System.out.println(Test.class.getClassLoader());//sun.misc.Launcher$AppClassLoader
    System.out.println(String.class.getClassLoader());//null(API中说明:一些实现 可能使用null来表示引导类加载器。 如果此类由引导类加载器加载,则此方法将在此类实现中返回null。 )
    }
}

(4)双亲委派机制

上图展示了"类加载器"的层次关系,这种关系称为类加载器的"双亲委派模型":

a."双亲委派模型"中,除了顶层的启动类加载器外,其余的类加载器都应当有自己的"父级类加载器"。

b.这种关系不是通过"继承"实现的,通常是通过"组合"实现的。通过"组合"来表示父级类加载器。

c."双亲委派模型"的工作过程:

i. 某个"类加载器"收到类加载的请求,它首先不会尝试自己去加载这个类,而是把请求交给父

级类加载器。

ii.因此,所有的类加载的请求最终都会传送到顶层的"启动类加载器"中。

iii.如果"父级类加载器"无法加载这个类,然后子级类加载器再去加载。

(5)双亲委派机制的好处

双亲委派机制的一个显而易见的好处是:Java的类随着它的类加载器一起具备了一种带有优先级的层次

关系。例如:java.lang.Object。它存放在rt.jar中。无论哪一个类加载器要加载这个类,最终都是委派

给处于顶端的"启动类加载器"进行加载,因此java.lang.Object类在程序的各种类加载器环境中都是同一

个类。

相反,如果没有"双亲委派机制",如果用户自己编写了一个java.lang.Object,那么当我们编写其它类

时,这种隐式的继承使用的将会是用户自己编写的java.lang.Object类,那将变得一片混乱。

  1. 反射的概述

(1)反射的引入

问题:IDEA中的对象是怎么知道类有哪些属性,哪些方法的呢?

答:通过反射技术对象类进行了解剖得到了类的所有成员。

(2)反射的概念

反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的所有成员(成员变量,成员方 法,构造方法)。

(3)使用反射操作类成员的前提

要获得该类字节码文件对象,就是Class对象。

(4)反射在实际开发中的应用

a.开发IDEA(集成开发环境),比如IDEA,Eclipse

b.各种框架的设计和学习 比如Spring,Mybaits....

  1. Class对象的获取方式

(1)三种获取方式

方式1: 通过类名.class获得

方式2:通过对象名.getClass()方法获得

方式3:通过Class类的静态方法获得: static Class forName("类全名")

每一个类的Class对象都只有一个。

示例代码:

package com.test.code.reflex;

public class Student {
}

public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获得Student类对应的Class对象
        Class<Student> c1 = Student.class;


        // 创建学生对象
        Student stu = new Student();
        Class<? extends Student> c2 = stu.getClass();
        System.out.println(c1 == c2);

        // 通过Class类的静态方法获得: static Class forName("类全名")
        Class<?> c3 = Class.forName("com.test.code.reflex.Student");
        System.out.println(c1 == c3);
        System.out.println(c2 == c3);

    }
}

Demo01运行结果:

(2)Class类常用方法

String getSimpleName(); 获得类名字符串:类名 
String getName(); 获得类全名:包名+类名 
T newInstance() ; 创建Class对象关联类的对象

示例代码:

public class Demo02 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 获得类名字符串:类名
        System.out.println(c.getSimpleName());

        // 获得类全名:包名 + 类名
        System.out.println(c.getName());

        // 创建对象
        Student stu = (Student)c.newInstance();
        System.out.println(stu);
    }
}

Demo02运行结果:

4.反射之操作构造方法

(1)Constructor类概述

反射之操作构造方法的目的:获得Constructor对象来创建类的对象。

Constructor类概述:类中的每一个构造方法都是一个Constructor类的对象

(2)Class类中与Constructor相关的方法

1. Constructor getConstructor(Class... parameterTypes)
* 根据参数类型获得对应的Constructor对象。
* 只能获得public修饰的构造方法
2. Constructor getDeclaredConstructor(Class... parameterTypes)
* 根据参数类型获得对应的Constructor对象
* 可以是public、protected、(默认)、private修饰符的构造方法。
3. Constructor[] getConstructors()
* 获得类中的所有构造方法对象,只能获得public的
4. Constructor[] getDeclaredConstructors()
* 获得类中的所有构造方法对象
* 可以是public、protected、(默认)、private修饰符的构造方法。

(3)Constructor对象常用方法

1. T newInstance(Object... initargs)"—— 根据指定的参数创建对象
2. void setAccessible(true) 设置"暴力反射"——是否取消权限检查,true取消权限检查,false表示不取消

示例代码:

public class Student {

    private String name;
    private String sex;
    private int age;

    //公有构造方法
    public Student(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    //私有构造方法
    private Student(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

}
public class Demo03 {

    /**
     * Constructor[] getConstructors()
     *      获得类中的所有构造方法对象,只能获得public的
     * Constructor[] getDeclaredConstructors()
     *      获得类中的所有构造方法,包括private修饰的
     */
    @Test
    public void test03(){
        // 获得Class对象
        Class<Student> c = Student.class;

        // 获得类中的所有构造方法对象,只能是public修饰的
        Constructor<?>[] cons_one = c.getConstructors();
        for (Constructor<?> con : cons_one) {
            System.out.println(con);
        }

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

        // 获取类中所有的构造方法,包括public、protected、(默认)、private的
        Constructor<?>[] cons_two = c.getDeclaredConstructors();
        for (Constructor<?> con : cons_two) {
            System.out.println(con);
        }

    }

    /**
     * Constructor getDeclaredConstructor(Class... parameterTypes)
     *      根据参数类型获得对应的Constructor对象
     */
    @Test
    public void test02() throws Exception {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 获得两个参数构造方法对象
        Constructor<Student> con = c.getDeclaredConstructor(String.class, String.class);
        // 取消权限检查(暴力反射)
        con.setAccessible(true);
        // 根据构造方法创建对象
        Student stu = con.newInstance("liuyifei", "女");
        System.out.println(stu);

    }

    /**
     * Constructor getConstructor(Class... parameterTypes)
     *      根据参数类型获得对应的Constructor对象
     */
    @Test
    public void test01() throws Exception {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 获得无参数构造方法对象 注意:记得在Student类中加无参构造方法,不然会报错
        Constructor<Student> con = c.getConstructor();

        // 根据构造方法创建对象
        Student student = con.newInstance();
        System.out.println(student);

        // 获得有参数的构造方法对象
        Constructor<Student> con2 = c.getConstructor(String.class, String.class, int.class);
        // 创建对象
        Student stu2 = con2.newInstance("jack", "男", 18);
        System.out.println(stu2);
    }

}

5.反射之操作成员方法

(1)Method类概述

反射之操作成员方法的目的:操作Method对象来调用成员方法
Method类概述:每一个成员方法都是一个Method类的对象。

(2)Class类中与Method相关的方法

* Method getMethod(String name,Class...args);
根据方法名和参数类型获得对应的构造方法对象,只能获得public的
* Method getDeclaredMethod(String name,Class...args);
根据方法名和参数类型获得对应的构造方法对象,包括public、protected、(默认)、private的
* Method[] getMethods();
获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的
* Method[] getDeclaredMethods();
获得类中的所有成员方法对象,返回数组,只获得本类的,包括public、protected、(默认)、 private的

(3)Method对象常用方法

* Object invoke(Object obj, Object... args)
调用指定对象obj的该方法
args:调用方法时传递的参数
* void setAccessible(true)
设置"暴力访问"——是否取消权限检查,true取消权限检查,false表示不取消

示例代码:

public class Demo04 {

    /**
     * Method[] getMethods();
     * 获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的
     * Method[] getDeclaredMethods();
     * 获得类中的所有成员方法对象,返回数组,只获得本类的,包含private修饰的
     */
    @Test
    public void test03() {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 获得类中的所有成员方法对象,返回数据,只能获得public修饰的且包含父类的
        // Method[] methods = c.getMethods();

        // 获得类中的所有成员方法对象,返回数组,只获得本类的,包含private修饰的
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }

    /**
     * Method getDeclaredMethod(String name,Class...args);
     * 根据方法名和参数类型获得对应的构造方法对象,
     */
    @Test
    public void test02() throws Exception {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 根据Class对象创建学生对象
        Student stu = c.newInstance();
        // 获得sleep方法对应的Method对象
        Method m = c.getDeclaredMethod("sleep");
        // 暴力反射
        m.setAccessible(true);
        // 通过m对象执行sleep方法
        m.invoke(stu);
    }

    /**
     * Method getMethod(String name,Class...args);
     * 根据方法名和参数类型获得对应的构造方法对象,
     */
    @Test
    public void test01() throws Exception {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 根据Class对象创建学生对象
        Student stu = c.newInstance();

//        // 获得study方法对应的Method对象
//        Method m = c.getMethod("study");
//        // 通过m对象执行study方法
//        m.invoke(stu);

        // 获得study方法对应的Method对象
        Method m2 = c.getMethod("study", int.class);
        // 通过m2对象执行study方法
        m2.invoke(stu, 8);
    }

}

6.反射之操作成员变量

(1)Field类概述

反射之操作成员变量的目的 :通过Field对象给对应的成员变量赋值和取值
Field类概述: 每一个成员变量都是一个Field类的对象。

(2)Class类中与Field相关的方法

Field getField(String name);
根据成员变量名获得对应Field对象,只能获得public修饰
Field getDeclaredField(String name);
根据成员变量名获得对应Field对象,包括public、protected、(默认)、private的
Field[] getFields();
获得所有的成员变量对应的Field对象,只能获得public的
Field[] getDeclaredFields();
获得所有的成员变量对应的Field对象,包括public、protected、(默认)、private的

(3)Field对象常用方法

void set(Object obj, Object value)
void setInt(Object obj, int i)
void setLong(Object obj, long l)
void setBoolean(Object obj, boolean z)
void setDouble(Object obj, double d)

Object get(Object obj)
int getInt(Object obj)
long getLong(Object obj)
boolean getBoolean(Object ob)
double getDouble(Object obj)

void setAccessible(true); // 暴力反射,设置为可以直接访问私有类型的属性。
Class getType(); // 获取属性的类型,返回Class对象。

setXxx方法都是给对象obj的属性设置使用,针对不同的类型选取不同的方法。

getXxx方法是获取对象obj对应的属性值的,针对不同的类型选取不同的方法。

示例代码:

public class Student {

    public String name;
    private String gender;

    public String toString() {
        return "Student [name = " + name + " , gender = " + gender + "]";
    }

}
public class Demo05 {

    /**
     * Field[] getFields();
     * 获得所有的成员变量对应的Field对象,只能获得public的
     * Field[] getDeclaredFields();
     * 获得所有的成员变量对应的Field对象,包含private的
     */
    @Test
    public void test02(){
        // 获得Class对象
        Class<Student> c = Student.class;

        // 获得所有的成员变量对应的Field对象
        // Field[] fields = c.getFields();

        // 获得所有的成员变量对应的Field对象,包括private
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }

    }

    /**
     * Field getField(String name);
     *      根据成员变量名获得对应Field对象,只能获得public修饰
     * Field getDeclaredField(String name);
     *      根据成员变量名获得对应Field对象,包含private修饰的
     */
    @Test
    public void test01() throws Exception {
        // 获得Class对象
        Class<Student> c = Student.class;

        // 创建对象
        Student stu = c.newInstance();

        // 获得成员变量name对应的Field对象
        Field f = c.getField("name");
        // 给成员变量name赋值
        // 给指定对象stu的name属性赋值为jack
        f.set(stu,"jack");

        // 获得指定对象stu成员变量name的值
        System.out.println(f.get(stu)); // jack
        //  获得成员变量的名字
        System.out.println(f.getName()); //name

        // 给成员变量gender赋值
        // 获得成员变量gender对应的Field对象
        Field f1 = c.getDeclaredField("gender");
        // 暴力反射
        f1.setAccessible(true);
        // 给指定对象stu的gender属性赋值为男
        f1.set(stu,"男");

        System.out.println(stu);
    }

}

wx 搜索“自律的西瓜L”

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/284.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从Linux内核中学习高级C语言宏技巧

Linux内核可谓是集C语言大成者,从中我们可以学到非常多的技巧,本文来学习一下宏技巧,文章有点长,但耐心看完后C语言level直接飙升。 本文出自:大叔的嵌入式小站,一个简单的嵌入式/单片机学习、交流小站 从Linux内核中学习高级C语言宏技巧 1.用do{}while(0)把宏包起来 …

《网络安全》零基础教程-适合小白科普

《网络安全》零基础教程 目录 目录 《网络安全》零基础教程 第1章 网络安全基础 什么是网络安全 常见的网络安全威胁 网络安全的三个基本要素 网络安全的保障措施 第2章 网络攻击类型 病毒、蠕虫、木马、后门 DoS、DDoS攻击 ​​​​​​​SQL注入、XSS攻击 ​​​…

测试背锅侠?入职软件测试后大d佬给我丢了这个bug分类分析,至今受益匪浅......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 刚成为入职&#xf…

测试场景设计

测试场景设计 又叫做场景法。其实对于场景法是测试用例中面临最多的&#xff0c;但是这种模式不是很容易总结&#xff0c;有时候是基于经验&#xff0c;有时候是我们对系统的了解。所以在这种情况下&#xff0c;我们强硬的用场景法对其进行规范。 场景法原理 现在的软件几乎…

vscode无法连接宝塔ftp排雷

宝塔面板现在使用率非常的高。今天把自己的踩坑处理方法记录一下。 在配置号宝塔面板ftp后&#xff0c;使用vscode的sftp插件&#xff0c;发现一直链接不上。一度以为自己配置文件&#xff0c;配置的参数有问题。各种度娘后&#xff0c;花了好长时间。后来发现自己陷入了误区。…

JS高级知识总结

文章目录1. this指向问题2. 对象进阶2.1 对象的定义和使用2.2 对象访问器2.2.1 Getter2.2.2 Setter2.3 对象构造器2.4 对象原型2.4.1 prototype属性2.4.2 \_\_proto\_\_ 属性2.4.3 constructor属性2.4.4 原型链2.5 Object对象2.5.1 管理对象2.5.2 保护对象3. 函数进阶3.1 函数的…

【Python】控制自己的手机拍照,并自动发送到邮箱

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 今天这个案例&#xff0c;就是控制自己的摄像头拍照&#xff0c; 并且把拍下来的照片&#xff0c;通过邮件发到自己的邮箱里。 想完成今天的这个案例&#xff0c;只要记住一个重点&#xff1a;你需要一个摄像头 思路…

8大主流编程语言的适用领域,你可能选错了语言

很多人学编程经常是脑子一热然后就去网上一搜资源就开始学习了&#xff0c;但学到了后面发现目前所学的东西并不是自己最喜欢的&#xff0c;好像自己更喜欢另一个技术&#xff0c;感觉自己学错了&#xff0c;于是乎又去学习别的东西。 结果竹篮打水一场空&#xff0c;前面所付…

蓝桥杯刷题冲刺 | 倒计时28天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.卡片2.数字三角形3.购物单4.回文日期1.卡片 题目 链接&#xff1a; 卡片 - 蓝桥云课 (lanqiao…

【计算机组成原理 - 第一章】计算机系统概论(完结)

本章参考王道考研相关课程&#xff1a; 【2021版】1.2.1_计算机硬件的基本组成_哔哩哔哩_bilibili 【2021版】1.2.2_认识各个硬件部件_哔哩哔哩_bilibili 【2021版】1.2.3_计算机系统的层次结构_哔哩哔哩_bilibili 【2021版】1.3_计算机的性能指标_哔哩哔哩_bilibili 目录 一、…

彻底搞懂nodejs事件循环

nodejs是单线程执行的&#xff0c;同时它又是基于事件驱动的非阻塞IO编程模型。这就使得我们不用等待异步操作结果返回&#xff0c;就可以继续往下执行代码。当异步事件触发之后&#xff0c;就会通知主线程&#xff0c;主线程执行相应事件的回调。 以上是众所周知的内容。今天…

14个Python处理Excel的常用操作,非常好用

自从学了Python后就逼迫用Python来处理Excel&#xff0c;所有操作用Python实现。目的是巩固Python&#xff0c;与增强数据处理能力。 这也是我写这篇文章的初衷。废话不说了&#xff0c;直接进入正题。 数据是网上找到的销售数据&#xff0c;长这样&#xff1a; 一、关联公式:…

人工智能轨道交通行业周刊-第35期(2023.2.20-2.26)

本期关键词&#xff1a;重庆智慧轨道、智能运维主机、标准轨距、地方铁路公报、景深、机器视觉应用 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通Rai…

【C/C++】必知必会知识点大总结

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…

基于Reactor模式下的epoll多路复用服务器

文章目录一、认识Reactor模式1.1 Reactor 模式的概念1.2 Reactor 模式的组件1.3 Reactor 模式的流程1.4 Reactor 模式的优点二、Reactor模式下的 epoll ET服务器2.1 总体设计思路2.2 Connection 类结构2.3 封装 socket 实现 Sock 类2.4 封装 epoll 实现 Epoller 类2.4.1 Create…

2023年BeijngCrypt勒索病毒家族最新变种之.halo勒索病毒

目录 前言&#xff1a;简介 一、什么是.halo勒索病毒&#xff1f; 二、.halo勒索病毒是如何传播感染的&#xff1f; 三、感染.halo后缀勒索病毒建议立即做以下几件事情 四、中了.halo后缀的勒索病毒文件怎么恢复&#xff1f; 五、加密数据恢复情况 六、系统安全防护措施建…

宣布推出 .NET 社区工具包 8.1!

我们很高兴地宣布 .NET Community Toolkit 8.1 版正式发布&#xff01;这个新版本包括呼声很高的新功能、bug 修复和对 MVVM 工具包源代码生成器的大量性能改进&#xff0c;使开发人员在使用它们时的用户体验比以往更好&#xff01; 就像在我们之前的版本中一样&#xff0c;我…

STM32F1硬件SPI驱动nRF24L01通过按键控制数据收发带状态反馈

STM32F1硬件SPI驱动nRF24L01通过按键控制数据收发带状态反馈&#x1f4cc;相关篇《STM32F1基于STM32CubeMX配置硬件SPI驱动nRF24L01数据收发》 &#x1f3ac;功能演示 &#x1f33f;工程默认配置的是STM32F103VC单片机&#xff0c;其他型号的修改需要修改启动文件startup_st…

python+django+vue图书个性化推荐系统

整个系统是由多个功能模块组合而成的&#xff0c;要将所有的功能模块都一一列举出来&#xff0c;然后进行逐个的功能设计&#xff0c;使得每一个模块都有相对应的功能设计&#xff0c;然后进行系统整体的设计。 本图书个性化推荐系统结构图如图python manage.py runserver 开…

宇宙最强-GPT-4 横空出世:最先进、更安全、更有用

文章目录前言一、准确性提升1.创造力2.视觉输入3.更长的上下文二、相比于ChatGPT有哪些提升1.GPT-4 的高级推理能力超越了 ChatGPT2.GPT-4 在多种测试考试中均优于 ChatGPT。三、研究团队在GPT-4模型都做了哪些改善1.遵循 GPT、GPT-2 和 GPT-3 的研究路径2.我们花了 6 个月的时…
最新文章