java—类反射机制

简述

        反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(如成员变量,构造器,成员方法等),并能操作对象的属性及方法。反射机制在设计模式和框架底层都能用到。

        类一旦加载,在堆中会产生一个Class类型的对象,这个对象包含了类的完整结构信息。通过这个对象可以获得这个类的结构。

java反射机制相关类

         java作为面向对象的编程语言,万物皆对象,在反射机制中,将类的各个成员都当做一个类的对象

    ①java.lang.Class:Class对象表示某个类加载后在堆中的对象
    ②java.lang.reflect.Method:代表类的方法
    ③java.lang.reflect.Field:代表类的成员变量
    ④java.lang.reflect.Constructor:代表类的构造器

反射机制优缺点

优点:可以动态的创建和使用对象,使用灵活,反射机制就是框架的底层支撑
缺点:使用反射的运行效率较慢

反射机制优化

        关闭访问检查,Method,Field,Constructor均有setAccessible(boolean b)方法,作用是开启或关闭访问安全检查开关,参数为true时关闭访问检查,提高反射的效率;参数为false则表示开启访问检查

Class

①Class类也是一个类,只是类名就叫做Class,因此也继承Object类
②Class类对象不是new Class()的形式创建的,而是由系统创建
③对于某一个类的Class类对象,在内存中只有一份,因此类在内存中只加载一次
④通过Class类对象可以获取所加载类的所有接信息
⑤Class对象存放在堆中。

具有Class对象的类型

类,接口,数组,枚举,注解,基本数据类型,void

代码示例:

package com.flash.class_;import java.io.Serializable;/*** @author flash* @date 2024/06/18 18:08* 功能描述:枚举拥有 Class 对象的类型*/
public class AllTypeClass {public static void main(String[] args) {// 类Class<String> cls1 = String.class;// 接口Class<Serializable> cls2 = Serializable.class;// 一维数组Class<Integer[]> cls3 = Integer[].class;// 二维数组Class<float[][]> cls4 = float[][].class;// 注解Class<Deprecated> cls5 = Deprecated.class;// 枚举Class<Thread.State> cls6 = Thread.State.class;// 基本数据类型Class<Long> cls7 = long.class;// voidClass<Void> cls8 = void.class;// ClassClass<Class> cls9 = Class.class;System.out.println("cls1 = " + cls1);System.out.println("cls2 = " + cls2);System.out.println("cls3 = " + cls3);System.out.println("cls4 = " + cls4);System.out.println("cls5 = " + cls5);System.out.println("cls6 = " + cls6);System.out.println("cls7 = " + cls7);System.out.println("cls8 = " + cls8);System.out.println("cls9 = " + cls9);}
}

运行结果:

类加载

基本说明:反射机制是java实现动态语言的关键, 也就是通过反射实现类动态加载
        ①静态加载:编译时加载相关的类, 如果没有直接报错, 依赖性强
        ②动态加载:运行时加载需要的类, 如果运行时没有用到该类, 即使不存在这个类也不会报错, 依赖性较弱
类加载时机:
        ①当创建对象时(new) 静态加载
        ②当子类被加载时, 父类也被加载 静态加载
        ③调用类中的静态成员时 静态加载
        ④反射机制 动态加载

Class类对象创建方式

import com.flash.classReflex.Car;/*** @author flash* @date 2024/06/18 16:28* 功能描述:演示得到 Class类 对象的各种方式*/
public class CreateClassInstance {public static void main(String[] args) throws ClassNotFoundException {// 1.class.forNameString classAllPath = "com.flash.classReflex.Car";// 通过读取配置文件获取Class<?> cls1 = Class.forName(classAllPath);System.out.println("cls1 = " + cls1);// 2.类名.class, 应用场景: 用于参数传递Class<Car> cls2 = Car.class;System.out.println("cls2 = " + cls2);// 3.通过已有类调用 getClass() 方法, getClass()获得的就是这个对象关联的 Class 的对象Car car = new Car();Class<? extends Car> cls3 = car.getClass();System.out.println("cls3 = " + cls3);// 4.通过类加载器获取到类的 Class 对象, 共4种// 先得到类加载器 carClassLoader classLoader = car.getClass().getClassLoader();// 通过类加载器得到 Class 对象Class<?> cls4 = classLoader.loadClass(classAllPath);System.out.println("cls4 = " + cls4);// cls1, cls2, cls3, cls4 一模一样System.out.println("cls1.hashCode = " + cls1.hashCode());System.out.println("cls2.hashCode = " + cls2.hashCode());System.out.println("cls3.hashCode = " + cls3.hashCode());System.out.println("cls4.hashCode = " + cls4.hashCode());// 5.基本数据类型按如下方式跌倒CLass类对象Class<Integer> integerClass = int.class;Class<Character> characterClass = char.class;Class<Boolean> booleanClass = boolean.class;// 输出的还是基本数据类型, 有一个自动装箱、拆箱的过程System.out.println("integerClass = " + integerClass);// intSystem.out.println("characterClass = " + characterClass);// charSystem.out.println("booleanClass = " + booleanClass);// boolean// 6.基本数据类型对应的包装类, 可以通过 .TYPE 对到 Class类对象Class<Integer> type = Integer.TYPE;Class<Character> type1 = Character.TYPE;Class<Boolean> type2 = Boolean.TYPE;// 还是会自动装箱拆箱System.out.println("type = " + type);System.out.println("type1 = " + type1);System.out.println("type2 = " + type2);System.out.println("integerClass.hashCode = " + integerClass.hashCode());// 1163157884System.out.println("type.hashCode = " + type.hashCode());// 1163157884// 二者相等, 说明基本数据类型及他的包装类的 Class类对象 是同一个}
}

运行结果:

反射获取类的结构信息

代码示例:

// 测试所用类
class PersonDad {public String dept;public PersonDad() {}public PersonDad(String dept) {this.dept = dept;}public void dadMethod() {}
}interface PersonInterface {}@Deprecated // 弃用注解
class Person extends PersonDad implements PersonInterface {// 属性public String name = "JSON";protected int age = 20;String job = "study";private double sal = -100;static int a;final int b = 10;public Person() {}public Person(String name) {this.name = name;}private Person(String dept, String job) {super(dept);this.job = job;}protected Person(String name, String job, String dept) {super(dept);this.name = name;this.job = job;}public Person(String dept, String name, int age, String job, double sal) {super(dept);this.name = name;this.age = age;this.job = job;this.sal = sal;}// 方法public void m1(String name, int age) {}protected int m2() {return 0;}String m3() {return null;}private void m4() {}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", job='" + job + '\'' +", sal=" + sal +", b=" + b +'}';}
}

获取类名

package com.flash.class_;import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** @author flash* @date 2024/06/19 14:05* 功能描述:通过反射获取类的结构信息*/
public class GetClassMessage {public static void main(String[] args) throws Exception {// 得到 Class 对象Class<?> personClass = Class.forName("com.flash.class_.Person");// getName:获取全类名System.out.println("获取全类名");System.out.println("name = " + personClass.getName());System.out.println("========================================");// getSimpleName:获取简单类名System.out.println("获取简单类名");System.out.println("SimpleName = " + personClass.getSimpleName());System.out.println("========================================");

运行结果:

获取属性

		// getFields:获取所有本类及其父类 public 修饰的属性System.out.println("获取所有本类及其父类 public 修饰的属性");for (Field field : personClass.getFields()) {System.out.println(field.getName());}System.out.println("========================================");// getDeclaredFields:获取本类所有属性, 只有本类的System.out.println("获取本类所有属性, 只有本类的");for (Field declaredField : personClass.getDeclaredFields()) {/*属性修饰符的值说明:默认修饰符: 0public: 1private: 2protected: 4static: 8final :16多修饰符时值相加*/System.out.println(declaredField.getType().getSimpleName() + " " + declaredField.getName() + " 属性修饰符的值 = " + declaredField.getModifiers());}System.out.println("========================================");

运行结果:

获取方法

        // getMethods:获取本类及其父类 public 方法System.out.println("获取本类及其父类 public 方法");for (Method method : personClass.getMethods()) {System.out.println(method.getName());}System.out.println("========================================");// getDeclaredMethods:获取本类所有方法, 只有本类的System.out.println("获取本类所有方法, 只有本类的");for (Method declaredMethod : personClass.getDeclaredMethods()) {System.out.println(declaredMethod.getReturnType().getSimpleName() + " " + declaredMethod.getName() + " 方法修饰符的值 = " + declaredMethod.getModifiers());System.out.print("参数:");for (Class<?> parameterType : declaredMethod.getParameterTypes()) {System.out.print(parameterType.getSimpleName() + " ");}System.out.println();}System.out.println("========================================");

运行结果:

获取构造器

        // getConstructors:获取本类 public 构造器System.out.println("获取本类 public 构造器");for (Constructor<?> constructor : personClass.getConstructors()) {System.out.println(constructor.getName());}System.out.println("========================================");// getDeclaredConstructors:获取本类所有构造器System.out.println("获取本类所有构造器");for (Constructor<?> declaredConstructor : personClass.getDeclaredConstructors()) {System.out.println(declaredConstructor.getName());System.out.print("参数:");for (Class<?> parameterType : declaredConstructor.getParameterTypes()) {System.out.print(parameterType.getSimpleName() + " ");}System.out.println();}System.out.println("========================================");

运行结果:

获取包信息、父类、实现接口、注解信息

        // getPackage:获取包信息System.out.println("获取包信息");System.out.println("Package = " + personClass.getPackage());System.out.println("========================================");// getSuperclass:获取父类System.out.println("获取父类");System.out.println(personClass.getSuperclass());System.out.println("========================================");// getInterfaces:获取本类实现的接口System.out.println("获取本类实现的接口");for (Class<?> anInterface : personClass.getInterfaces()) {System.out.println(anInterface.getName());}System.out.println("========================================");// getAnnotations:获取注解信息System.out.println("获取注解信息");for (Annotation annotation : personClass.getAnnotations()) {System.out.println("annotation = " + annotation);}}
}

运行结果:

反射创建实例对象

package com.flash.class_;import java.lang.reflect.Constructor;/*** @author flash* @date 2024/06/19 15:11* 功能描述:通过反射创建对象*/
public class CreateInstance {public static void main(String[] args) throws Exception {// 1.获取 Person 类的 Class对象Class<?> userClass = Class.forName("com.flash.class_.Person");// 2.通过public无参构造器创建实例对象Object o = userClass.newInstance();System.out.println("o = " + o);// 3.通过public构造器创建实例对象// 3.1 创建对应构造器Constructor<?> constructor = userClass.getConstructor(String.class);/*此时 constructor构造器 对应public Person(String name) {this.name = name;}*/// 3.2 通过刚才创建的构造器对象传入实参创建对应对象Object o1 = constructor.newInstance("张三");System.out.println("o1 = " + o1);// 4.调用非public构造器// 4.1 创建对应构造器Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, String.class);// 4.2 本身不能使用 私有 的构造器, 可以设置允许使用, 暂时先理解为暴力破解declaredConstructor.setAccessible(true);// 4.3 创建对象Object o2 = declaredConstructor.newInstance("山理工", "李四");System.out.println("o2 = " + o2);System.out.println(userClass.getField("dept").get(o2));// 5.试一下protectedConstructor<?> constructor1 = userClass.getDeclaredConstructor(String.class, String.class, String.class);// 非私有的构造方法方法不需要破解也可以使用Object o3 = constructor1.newInstance("老六", "happy", "打妖怪");System.out.println("o3 = " + o3);System.out.println(userClass.getField("dept").get(o3));}
}

运行结果:

反射访问属性

package com.flash.class_;import java.lang.reflect.Field;/*** @author flash* @date 2024/06/19 16:13* 功能描述:反射访问类中的属性及修改*/
public class AskProperty {public static void main(String[] args) throws Exception {Class<?> stuClass = Class.forName("com.flash.class_.Student");Object o = stuClass.newInstance();// o的运行类型已经是 Student 了System.out.println("o的运行类型 = " + o.getClass());// 使用反射得到 age 属性对象Field age = stuClass.getField("age");age.set(o, 88);System.out.println(o);// 使用反射操作 name 属性, 私有且静态Field name = stuClass.getDeclaredField("name");// 破解name.setAccessible(true);// 赋值name.set(null, "JSON");// 可以为 null, 因为 name 属性就是静态的// name.set(o, "JSON");// 输出System.out.println(o);// 获取单一属性System.out.println(name.get(o));// 获取属性 name 的值}
}class Student {private static String name;public int age;public Student() {}private static String staticMethod() {System.out.println("我是私有的静态方法");return "私有的静态方法";}public void hi(String s) {System.out.println("hi~" + s);}@Overridepublic String toString() {return "Student{" +"name=" + name + ", " +"age=" + age +'}';}
}

运行结果:

反射调用方法

package com.flash.class_;import java.lang.reflect.Method;/*** @author flash* @date 2024/06/19 16:24* 功能描述:通过反射调用方法*/
public class UseMethod {public static void main(String[] args) throws Exception {Class<?> stuClass = Class.forName("com.flash.class_.Student");// 创建一个 Student 对象
//        Object o = stuClass.newInstance();Object o = stuClass.getConstructor().newInstance();// 调用 public 方法Method hi = stuClass.getMethod("hi", String.class);
//        Method hi = stuClass.getDeclaredMethod("hi", String.class);// 调用 对象o 的 hi 方法hi.invoke(o, "JSON");// 调用私有的静态方法Method staticMethod = stuClass.getDeclaredMethod("staticMethod");// 爆破staticMethod.setAccessible(true);// 调用方法Object invoke = staticMethod.invoke(null);// 返回类型统一为 Object类型, 运行类型该是什么还是什么System.out.println("返回值invoke运行类型: " + invoke.getClass());System.out.println("invoke = " + invoke);
//        System.out.println(staticMethod.invoke(o));// 因为是静态方法, 所以有没有指定对象都可以调用}
}

运行结果:

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

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

相关文章

Java程序之让气球上升

问题&#xff1a; ACM比赛时间再次举行&#xff01;看到气球四处漂浮是多么的兴奋啊。但要告诉你一个秘密&#xff0c;评委们最喜欢的时间是猜测最流行的问题。比赛结束后&#xff0c;他们会数出每种颜色的气球&#xff0c;然后找到结果。今年&#xff0c;他们决定把这份可爱的…

【建设方案】基于gis地理信息的智慧巡检解决方案(源文件word)

传统的巡检采取人工记录的方式&#xff0c;该工作模式在生产中存在很大弊端&#xff0c;可能造成巡检不到位、操作失误、观察不仔细、历史问题难以追溯等现象&#xff0c;使得巡检数据不准确&#xff0c;设备故障隐患得不到及时发现和处理。因此建立一套完善的巡检管理系统是企…

Java程序之寻找自幂数

题目&#xff1a; 自幂数是指一个 n 位数&#xff08;3≤n≤7 &#xff09;&#xff0c;它的每个位上的数字的 n 次幂之和等于它本身&#xff08;例如&#xff1a;1^3 5^3 3^3 153&#xff1b;1^46^43^44^41634&#xff09;。三位自幂数&#xff1a;水仙花数&#xff1b;四位…

HeidiSQL导入与导出数据

HeidiSQL两种导入与导出数据的方法&#xff1a;整个库复制&#xff0c;和仅复制数据 一 整个库复制 1 选中需要导出的数据库(这里是MyDBdata)&#xff0c;点击导出为SQL脚本。 2 按照如图进行选择 3 选做&#xff1a;删除当前数据库【如果有】 -- 删除数据库 USE mysql; D…

python-题库篇-Python语言特性

文章目录 Python语言特性1 Python的函数参数传递2 Python中的元类(metaclass)3 staticmethod和classmethod4 类变量和实例变量5 Python自省6 字典推导式7 Python中单下划线和双下划线8 字符串格式化:%和.format9 迭代器和生成器10 *args and **kwargs11 面向切面编程AOP和装饰器…

基于SpringBoot+大数据城市景观画像可视化设计和实现

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

C语言入门系列:初识函数

文章目录 一&#xff0c;C语言函数与数学函数的区别1&#xff0c;回忆杀-初中数学2&#xff0c;C语言中的函数 二&#xff0c; 函数的声明1&#xff0c;函数头1.1&#xff0c;函数名称1.2&#xff0c;返回值类型1.3&#xff0c;参数列表 2&#xff0c;函数体2.1&#xff0c;函数…

Android使用zxing生成二维码

效果图如下&#xff1a; **前提&#xff1a;导入zxing的jar后开始操作&#xff0c;老规矩最后有源码&#xff0c;作者布局默认相对布局。 第一步&#xff1a;定义二维码的长宽高及图片控件** 第二步&#xff1a;实例化QRCodeWriter后利用for循环将二维码画出来&#xff0c;然后…

用Visual Studio调试CMake项目并生成Visual Studio工程

一. 在Windows系统上安装CMake 访问CMake官方网站https://cmake.org/download&#xff0c;或通过文末链接下载&#xff1a;在下载页面上&#xff0c;找到并点击“Download”链接以获取最新的稳定版本的CMake。请注意&#xff0c;虽然新版本可能包含更多功能和改进&#xff0c;…

关于DrawTools的分析- 一个优秀的C#开源绘图软件

国外大佬&#xff0c;曾经写过两个关于DrawTools相关的开源绘图软件。 我更新了一个优化的版本如下图&#xff0c;稍后会发布更新给大家。 需要的用户可发邮件给我 448283544qq.com 应用于AGV地图编辑器如下&#xff1a; 那么这个优于很多普通的画布软件&#xff0c;包含点、…

qt 简单实验 读取json格式的配置文件

1.概要 2.代码 //#include "mainwindow.h"#include <QApplication> #include <QFile> #include <QJsonDocument> #include <QJsonObject> #include <QDebug> //读取json数据的配置文件QJsonObject readJsonConfigFile(const QString …

iptables动作总结

ACCEPT动作 将数据包放行&#xff0c;进行完此处理动作后&#xff0c;将不再比对当前链的其它规则&#xff0c;直接跳往下一个规则链。 范例如下&#xff1a; #新增自定义链TEST_ACCEPTiptables -t filter -N TEST_ACCEPT#新增自定义链TEST_ACCEPT2iptables -t filter -N TES…

0基础学习线段树

前言&#xff1a; 线段树&#xff1a;用树来表示一个一个的线段区间。 1、为什么要使用线段树&#xff1f; 题目&#xff1a;给定一个数组nums&#xff0c;我们有两种下面两种操作 1、查询nums数组下标i到下标j的和&#xff1b; 2、将nums数组指定下标的值改为指定的一个新…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-28批量规范化

28批量规范化 """可持续加速深层网络的收敛速度""" import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as pltdef batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum):""&quo…

Swift 中的动态数组

Swift 的 Array 类型是一种强大而灵活的集合类型&#xff0c;可以根据需要自动扩展或缩减其容量。 动态数组的基本概念 Swift 中的数组是基于动态数组&#xff08;dynamic array&#xff09;的概念实现的。动态数组能够根据需要自动调整其容量&#xff0c;以容纳新增的元素&a…

Benchmarking Panoptic Scene Graph Generation (PSG), ECCV‘22 场景图生成,利用PSG数据集

2080-ti显卡复现 源代码地址 Jingkang50/OpenPSG: Benchmarking Panoptic Scene Graph Generation (PSG), ECCV22 (github.com) 安装 pytorch 1.7版本 cuda10.1 按照readme的做法安装 我安装的过程如下图所示,这个截图是到了pip install openmim这一步 下一步 下一步 这一步…

C语言 | Leetcode C语言题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {int* ret (int*)malloc(sizeof(int) * 2);*returnSize 2;int low 0, high numbersSize - 1;while (low < high) {int sum numbers[low] numbers[high]…

如何设置MySQL远程访问权限?

MySQL是一种流行的关系型数据库管理系统&#xff0c;它广泛应用于各种Web应用程序和数据驱动的应用中。在默认情况下&#xff0c;MySQL只允许本地访问&#xff0c;为了能够从远程服务器或客户端访问MySQL数据库&#xff0c;我们需要进行一些额外的设置和配置。 安装和配置MySQ…

在阿里云使用Docker部署MySQL服务,并且通过IDEA进行连接

阿里云使用Docker部署MySQL服务&#xff0c;并且通过IDEA进行连接 这里演示如何使用阿里云来进行MySQL的部署&#xff0c;系统使用的是Linux系统 (Ubuntu)。 为什么使用Docker? 首先是因为它的可移植性可以在任何有Docker环境的系统上运行应用&#xff0c;避免了在不通操作系…

【html】用html+css实现银行的账户信息表格

我们先来看一看某银行的账户信息表格 我们自己也可以实现类似的效果 效果图: 大家可以看到&#xff0c;其实效果差不多 接下来看看我们实现的代码 源码&#xff1a; <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"&…