Java入坑之反射研究

news2024/9/23 21:22:33

一、快速入门

1.1反射概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象

1.2反射功能 

反射:reflection
-程序可以访问、检测和修改它本身状态或行为的能力,即自描述
和自控制。
-可以在运行时加载、探知和使用编译期间完全未知的类。
-给Java插上动态语言特性的翅膀,弥补强类型语言的不足。
- java.lang.reflect包,在Java 2时代就有,在Java 5得到完善

 1.3创建对象的方式

1.3.1静态编码&编译

效率最好,方法写死无法实现A类换B类(硬性编码) 

1.3.2克隆

 JAVA四大接口

Comparable:用于对象比较的接口;
Runnable :用于对象线程化的接口;
Serializable:用于对象序列化的接口;
Clonable:用于对象克隆的接口。

1.3.3序列化

 1.3.4反射

二、反射关键类

2.1Class类型标识

-JVM为每个对象都保留其类型标识信息(RuntimeTypeIdentification)

package org.example;

// 导入 java.lang 包,该包包含了基本的类,如 String, Class, System 等
import java.lang.*;
// 定义一个公共类 Main,包含主方法
public class a {
    // 主方法,程序的入口
    public static void main(String[] args) {
        // 调用上面给出的代码段,作为一个静态方法
        testClass();
    }

    // 定义一个静态方法 testClass,用来测试获取 Class 对象的三种方式
    public static void testClass() {
        // 创建一个字符串对象 s1
        String s1 = "abc";
        // 通过调用 s1 的 getClass 方法,获取其对应的 Class 对象 c1
        Class c1 = s1.getClass();
        // 打印 c1 的名称,即 java.lang.String
        System.out.println(c1.getName());
        // 通过调用 Class 类的静态方法 forName,传入一个类的全限定名,获取其对应的 Class 对象 c2
        try {
            Class c2 = Class.forName("java.lang.String");
            // 打印 c2 的名称,也是 java.lang.String
            System.out.println(c2.getName());
        } catch (ClassNotFoundException e) {
            // 如果找不到指定的类,捕获异常并打印错误信息
            e.printStackTrace();
        }
        // 通过使用类名后面加上 .class 的语法,获取其对应的 Class 对象 c3
        Class c3 = String.class;
        // 打印 c3 的名称,同样是 java.lang.String
        System.out.println(c3.getName());
    }
}

 常见方法

getMethods () :返回本类和所有父类所有的public方法;
getDec lar edMethods() :返回本类自己定义的方法,包括pr ivate的方法,但不包括父类的方法。 

2.2Field方法

package org.example;// 导入 java.lang 包,该包包含了基本的类,如 String, Class, System 等
import java.lang.*;
// 导入 java.lang.reflect 包,该包包含了反射相关的类,如 Field, Method 等
import java.lang.reflect.*;
// 定义一个类 b
class b {
    // 定义两个字段 age 和 name
    public int age;
    private String name;
    // 定义一个构造方法,接收两个参数 age 和 name,并赋值给字段
    public b(int age, String name) {
        this.age = age;
        this.name = name;
    }

  

    // 定义一个静态方法 main,程序的入口
    // 在方法上添加 throws 子句,声明可能抛出的 IllegalAccessException 异常
    public static void main(String[] args) throws IllegalAccessException {
        // 创建一个 b 类的对象 obj,并传入参数 20 和 "Tom"
        b obj = new b(20, "Tom");
        // 通过调用 obj 的 getClass 方法,获取其对应的 Class 对象 c
        Class c = obj.getClass();
        // 获取本类及父类所有的 public 字段,并存储在数组 fs 中
        Field[] fs = c.getFields();
        // 打印 fs 数组中第一个元素(即 age 字段)的名称和值
        System.out.println(fs[0].getName() + ":" + fs[0].get(obj));
        // 获取本类所有声明的字段,并存储在数组 fs2 中
        Field[] fs2 = c.getDeclaredFields();
        // 使用 for-each 循环遍历 fs2 数组中的每个元素 f
        for (Field f : fs2) {
            // 设置 f 可访问,以便访问私有字段
            f.setAccessible(true);
            // 打印 f 的名称和值
            System.out.println(f.getName() + ":" + f.get(obj));
        }
    }
}

 2.3Method:成员方法

package org.example;

// 导入 java.lang 包,该包包含了基本的类,如 String, Class, System 等
import java.lang.*;
// 导入 java.lang.reflect 包,该包包含了反射相关的类,如 Field, Method 等
import java.lang.reflect.*;
// 导入 java.io 包,该包包含了输入输出相关的类,如 PrintStream, PrintWriter 等
import java.io.*;
// 定义一个类 B
class B {
    // 定义一个公共方法 f1,无参数,无返回值
    public void f1() {
        // 定义一个局部变量 t1,并赋值为 0
        int t1 = 0;
        // 使用 System 类的 out 字段,调用 println 方法,打印一条信息
        System.out.println("B.f1()...");
    }
    // 定义一个私有方法 f2,接收一个字符串参数 s,返回一个字符串值
    private String f2(String s) {
        // 使用 System 类的 out 字段,调用 println 方法,打印一条信息
        System.out.println("B.f2()...");
        // 返回参数 s
        return s;
    }
    // 定义一个静态方法 main,程序的入口
    // 在方法上添加 throws 子句,声明可能抛出的异常
    public static void main(String[] args) throws Exception {
        // 创建一个 B 类的对象 obj,并传入参数 20 和 "Tom"
        B obj = new B();
        // 通过调用 obj 的 getClass 方法,获取其对应的 Class 对象 c
        Class c = obj.getClass();
        // 获取本类及父类所有的 public 方法,并存储在数组 ms 中
        Method[] ms = c.getMethods();
        // 使用 for-each 循环遍历 ms 数组中的每个元素 m
        for (Method m : ms) {
            // 如果 m 的名称等于 "f1"
            if ("f1".equals(m.getName())) {
                // 调用 m 的 invoke 方法,传入 obj 和 null 作为参数,执行 f1 方法
                m.invoke(obj, null);
            }
        }
        // 获取本类所有声明的方法,并存储在数组 ms2 中
        Method[] ms2 = c.getDeclaredMethods();
        // 使用 for-each 循环遍历 ms2 数组中的每个元素 m
        for (Method m : ms2) {
            // 如果 m 的名称等于 "f2"
            if ("f2".equals(m.getName())) {
                // 设置 m 可访问,以便访问私有方法
                m.setAccessible(true);
                // 调用 m 的 invoke 方法,传入 obj 和一个包含 "abc" 的 Object[] 类型的数组作为参数,执行 f2 方法,并接收返回值 result
                String result = (String) m.invoke(obj, new Object[]{"abc"});
                // 使用 System 类的 out 字段,调用 println 方法,打印返回值 result
                System.out.println(result);
            }
        }
    }
}

2.4Constructor:构造函数

package org.example;

// 导入 java.lang 包,该包包含了基本的类,如 String, Class, System 等
import java.lang.*;
// 导入 java.lang.reflect 包,该包包含了反射相关的类,如 Field, Method, Constructor 等
import java.lang.reflect.*;
// 定义一个类 D
class D {
    // 定义一个私有字段 num
    private int num;
    // 定义一个无参构造函数
    public D() {
        // 给 num 赋值为 0
        this.num = 0;
    }
    // 定义一个有参构造函数
    public D(int num) {
        // 给 num 赋值为参数 num
        this.num = num;
    }
    // 定义一个公共方法 printNum,无参数,无返回值
    public void printNum() {
        // 使用 System 类的 out 字段,调用 println 方法,打印 num 的值
        System.out.println(this.num);
    }
    // 定义一个静态方法 main,程序的入口
    // 在方法上添加 throws 子句,声明可能抛出的异常
    public static void main(String[] args) throws Exception {
        // 创建一个 D 类的对象 d,并使用无参构造函数
        D d = new D();
        // 通过调用 d 的 getClass 方法,获取其对应的 Class 对象 c
        Class c = d.getClass();
        // 获取本类所有声明的构造函数,并存储在数组 cons 中
        Constructor[] cons = c.getConstructors();
        // 使用 for-each 循环遍历 cons 数组中的每个元素 con
        for (Constructor con : cons) {
            // 如果 con 的参数个数为 1
            if (con.getParameterCount() == 1) {
                // 有参构造函数
                // 调用 con 的 newInstance 方法,传入一个包含 100 的 Object[] 类型的数组作为参数,创建一个 D 类的对象 obj,并强制转换为 D 类型
                D obj = (D) con.newInstance(new Object[]{100});
                // 调用 obj 的 printNum 方法,打印 num 的值
                obj.printNum();
            } else {
                // 无参构造函数
                // 调用 con 的 newInstance 方法,传入一个空的 Object[] 类型的数组作为参数,创建一个 D 类的对象 obj,并强制转换为 D 类型
                D obj = (D) con.newInstance(new Object[]{});
                // 调用 obj 的 printNum 方法,打印 num 的值
                obj.printNum();
            }
        }
    }
}

2.5父类/父类接口

package org.example;

// 导入 java.lang 包,该包包含了基本的类,如 String, Class, System 等
import java.lang.*;
// 定义一个类 Father
class Father {
}
// 定义一个类 Son,并继承了 Father 类,并实现了 Cloneable 和 Comparable 接口
class Son extends Father implements Cloneable, Comparable {
    // 定义一个受保护的方法 clone,并抛出了 CloneNotSupportedException 异常
    protected Object clone() throws CloneNotSupportedException {
        // 返回父类的 clone 方法的结果
        return super.clone();
    }
    // 定义一个公共的方法 compareTo,并接收了一个 Object 类型的参数 o
    public int compareTo(Object o) {
        // 返回 0
        return 0;
    }
    // 定义一个静态方法 main,程序的入口
    public static void main(String[] args) {
        // 创建一个 Son 类的对象 son,并使用无参构造函数
        Son son = new Son();
        // 通过调用 son 的 getClass 方法,获取其对应的 Class 对象 c
        Class c = son.getClass();
        // 获取父类的 Class 对象,并存储在变量 father 中
        Class father = c.getSuperclass();
        // 使用 System 类的 out 字段,调用 println 方法,打印 father 的名称
        System.out.println(father.getName());
        // 获取实现的接口,并存储在数组 inters 中
        Class[] inters = c.getInterfaces();
        // 使用 for-each 循环遍历 inters 数组中的每个元素 inter
        for (Class inter : inters) {
            // 使用 System 类的 out 字段,调用 println 方法,打印 inter 的名称
            System.out.println(inter.getName());
        }
    }
}

三、反射应用

3.1数组扩容

package org.example;

import java.lang.reflect.Array;

public class ArrayCopyExample {
    public static void main(String[] args) {
        int[] oldArray = {1, 2, 3, 4, 5};
        int newLength = 10;

        int[] newArray = (int[]) goodCopy(oldArray, newLength);

        System.out.println("Original array:");
        printArray(oldArray);

        System.out.println("New array after copying:");
        printArray(newArray);
    }

    // 用于将旧数组的内容复制到新数组中
    public static Object goodCopy(Object oldArray, int newLength) {
        // 获取数组类型
        Class<?> c = oldArray.getClass();
        // 获取数组中的元素类型
        Class<?> componentType = c.getComponentType();
        // 获取旧数组的长度
        int oldLength = Array.getLength(oldArray);
        // 创建一个新数组
        Object newArray = Array.newInstance(componentType, newLength);
        // 使用 System.arraycopy 方法将旧数组的内容复制到新数组中
        System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldLength, newLength));
        return newArray;
    }

    // 打印数组内容
    public static void printArray(Object array) {
        int length = Array.getLength(array);
        for (int i = 0; i < length; i++) {
            System.out.print(Array.get(array, i) + " ");
        }
        System.out.println();
    }
}

3.2动态执行方法

package org.example;

import java.util.Timer;
import java.util.TimerTask;
import java.util.Calendar;
import java.util.Date;

public class TimerExample {
    public static void main(String[] args) {
        // 创建一个定时器
        Timer timer = new Timer();

        // 获取当前时间
        Calendar now = Calendar.getInstance();
        // 设置任务开始时间,推迟1秒
        now.set(Calendar.SECOND, now.get(Calendar.SECOND) + 1);
        Date runDate = now.getTime();

        // 创建任务实例
        MyTask task = new MyTask();
        // 将任务安排在指定的开始时间开始执行,每隔3秒执行一次
        timer.scheduleAtFixedRate(task, runDate, 3000);
    }
}

class MyTask extends TimerTask {
    public void run() {
        try {
            // 调用 Worker 类的 hello 方法
            Worker.hello();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Worker {
    public static void hello() {
        System.out.println("Hello java!");
    }
}

3.3Json和Java对象互转

3.4Tomcat的Servlet创建

 3.5第三方库

四、编译器API 

4.1相关知识

 JDK提供javac工具来编译.java源文件,但我们没法深入javac工具了解其内部,只能通过Runtime命令行调用javac工具来进行动态编译(仅仅调用,无法深入控制编译过程)。而编译器API提供了一套完整的API,使得可以在程序中对其他源文件进行更细粒度的编译控制。

4.2JavaCompiler

4.3 编译器API 作用

4.4相关集成工具 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十一:通用表单组件封装实现

一、本章内容 本章实现通用表单组件,根据实体配置识别实体属性,并自动生成编辑组件,实现对应数据填充、校验及保存等逻辑。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址:

【Pandas 入门-5】Pandas 画图

Pandas 画图 除了结合 matplotlib 与 seaborn 画图外&#xff0c;Pandas 也有自己的画图函数plot&#xff0c;它的语法一般为&#xff1a; DataFrame.plot(xNone,yNone, kindline,subplotsFalse, titleNone)x横坐标数据y纵坐标数据kind默认是线图&#xff0c;还可以是‘bar’…

旅行旅游景点门票价格路线展示h5小程序开源版开发

旅行旅游景点门票价格路线展示h5小程序开源版开发 景点门票价格查询&#xff1a;用户可以通过输入景点名称或地址来查询该景点的门票价格。景点路线推荐&#xff1a;根据用户的出发地和目的地&#xff0c;提供最佳的旅游路线推荐。路线规划&#xff1a;用户可以在地图上选择多…

基于ssm+vue网上拍卖系统源码和论文

基于ssmvue网上拍卖系统源码和论文114 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 研究目的和意义: 1、研究目的 随着网络技术的不断发展和人们购物意识的不断革新&#xff0c;网上购物成为一种主流的购…

技术领导力实战笔记25

25&#xff5c;用心做好“鼓励式”管理 激发正能量 授权 分工作&#xff1a; 老人干新事&#xff0c;新人干老事&#xff0c;强者干难事&#xff0c;弱者干细事 新人干老事 所谓新人&#xff0c;是对业务产品不了解&#xff0c;对工作流程不清晰的岗位新人。对于新人来说&…

开发高效智能美妆算法:美颜SDK的关键技术解析

在当今社交媒体和视频直播的时代&#xff0c;人们越来越关注如何在虚拟世界中展现最佳的自己。美颜技术在此背景下应运而生&#xff0c;而其中的关键技术在开发高效智能美妆算法方面扮演了重要角色。本文将深入探讨美颜SDK的关键技术&#xff0c;揭示其背后的原理与创新。 一…

微信小程序字符串转时间的坑

目录 一、测试环境 二、问题现象 三、总结 先说结论&#xff0c;字符串转时间支持yyyy/MM/dd格式&#xff0c;我们常见的yyyy-MM-dd格式有兼容性问题。处理方式: new Date(dateString.replace(/-/g, "/")) 一、测试环境 微信版本8.0.40&#xff0c;手机苹果XR&…

go学习part20(2)反射细节

1.反射细节 1) reflect.Value.Kind&#xff0c;获取变量的类别&#xff0c;返回的是一个常量&#xff08;看手册) 2&#xff09;Type是类型,Kind是类别 Type和Kind可能是相同的&#xff0c;也可能是不同的. 比如: var num int 10 num的Type是int , Kind也是int 比如: var…

1Java:JDK是什么

1Java是介于编译型语言和解释型语言之间 编译型语言&#xff1a;c c先编译成机器码&#xff0c;再执行 解释型语言&#xff1a;pytn 解释器直接加载源码运行&#xff0c;但是运行效果低 Java是将代码编译成一张字节码,优点 针对不同平台编写虚拟机&#xff0c;不同平台的虚拟…

【ctf题目系列】ctfwiki pwn类型

categories: ctf ret2shellcode [rootningan ret2shellcode]# ./ret2shellcode No system for you this time !!! 123 bye bye ~[rootningan ret2shellcode]#checksec检查 [rootningan ret2shellcode]# checksec ret2shellcode [!] Could not populate PLT: future feature …

二维数组创建方式比较

暑假跟着地质队去跑山了&#xff0c;到现在还没结束&#xff0c;今天休息的时候突然刷到了一篇关于C二维数组创建方面的文章&#xff0c;我觉得还是非常不错滴&#xff0c;就将其中提到的新方法和我已经使用过的三种方法进行了比较&#xff0c;发现该方法提高了二维数组的分配、…

机器学习前沿:改进自身缺陷,满足新战略

前机械师&#xff08; 来源) 一、说明 机器学习在人工智能历史上扮演重要角色&#xff0c;然而&#xff0c;存在问题也不少。为了适应新时代和新任务&#xff0c;不做出重大改进是不可能的&#xff0c;本篇就一些突出问题和改进做出讨论。以便读者掌握未来的思路和方向。 二、机…

Python自动化运维之命令行参数(sys、argparse模块)

目录 一、sys.argv属性变量 二、argparse模块 一、sys.argv属性变量 sys.argv变量里面保存着命令行的参数列表。首个元素值为执行py脚本文件所在的路径。可以使用切片的方式来获取非脚本文件名的其它所有参数。 二、argparse模块 可以轻松地编写出用户体验友好的命令行界面…

【Linux】线程安全-互斥同步

文章目录 线程安全问题的引入线程互斥互斥概念互斥锁互斥锁的计数器当中如何保证原子性互斥锁基础API初始化互斥锁变量函数动态初始化静态初始化 加锁函数阻塞加锁非阻塞加锁带有超时时间的加锁 解锁函数销毁互斥锁函数 线程同步线程同步的必要性条件变量条件变量的使用原理条件…

冠达管理:龙头股票是什么意思?

龙头股票是指在某个职业或板块中市值最大、盈余才能最强、发展前景最好的上市公司。可以说&#xff0c;龙头股票是该职业或板块的代表。 那么&#xff0c;为什么龙头股票具有如此重要的地位&#xff1f;与其他股票比较&#xff0c;有哪些优势和下风&#xff1f;这篇文章将从多…

Stable Diffusion 从入门到企业级应用010

一、前言 本文是《Stable Diffusion 从入门到企业级应用实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》的第010篇 利用Stable Diffusion ControlNet 法线贴图模型精准控制图像生成。本部分内容&#xff0c;位于整个Stable Diffusion生态体…

节能减排数远程控制二次开发网关BL304

钡铼技术嵌入式ARM控制器BL304在各个领域的应用越来越广泛。从物联网、工业物联网&#xff0c;到数字化工厂、工业自动化&#xff0c;再到智慧医疗、智慧电力、智慧安防&#xff0c;以及车载、轨道交通、通讯、充电桩、智能家居、人机交互等&#xff0c;BL304都发挥着举足轻重的…

哈弗枭龙MAX将在9月上旬推出首次OTA升级,保不住电?不存在的

9月1日消息&#xff0c;哈弗品牌执行副总经理乔心昱昨晚通过个人微博向网友们回应了关于哈弗枭龙MAX电池保持的问题。乔心昱表示&#xff0c;在与紧急技术团队确认后&#xff0c;他首先澄清了一个误会&#xff1a;大家可以放心使用&#xff0c;正常情况下没有电池问题。 此外&a…

2023开学啦《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

2023开学啦《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书

【UE 材质】常用向量运算节点——点积、叉积、归一化

目录 一、点积 二、叉积 三、归一化 一、点积 点积&#xff0c;也称为内积或数量积&#xff0c;是一种用于计算两个向量之间关系的操作。对于两个三维向量 A&#xff08;a1,a2,a3&#xff09;和 B(b1,b2,b3)&#xff0c;它们的点积可以用以下公式表示&#xff1a; ABa1​⋅…