新数据结构(11)——Java类的产生和反射

反射是获取类信息的一种能力

类信息包括属性、方法、构造器、父类、接口等

类信息的来源

来自类的加载器,这是从.class文件到内存中的java虚拟器(JVM)中间的一个阶段(如下图)

类的加载器里,用Field数组存储成员变量,用method数组存储方法,用constructor存储构造器(如上图)。

Java运行流程分为三个阶段,其中第一个阶段在磁盘,第二三阶段(Class类对象阶段、Runtime运行时阶段)在内存(如上图)

三个阶段获取信息方式不同,第一阶段通过Class.forName("全类名"),第二阶段通过类名.class,第三个阶段通过对象名.getClass(),如下代码:

Class clazz1 = Class.forName("xxx");
Class clazz2 = Student.class;
Student student = new Student();
Class clazz3 = student.getClass();

 上面代码里的clazz1、clazz2、clazz3指向相同地址,其是一个对象

类信息的获取

通过Class.forName("Test20250218.Student")获取到Student类的Class对象。这一步是反射的基础,它允许程序在运行时动态地加载类。Test20250218.Student是类的全限定名,即包括包名和类名。接着,使用clazz.getDeclaredFields()获取Student类声明的所有字段,包括私有字段。这些字段被封装在Field数组中返回。然后,通过System.out.println(Arrays.toString(fields))将这些字段信息打印出来。随后,clazz.getFields()方法被调用,它返回的是类中所有可访问的公共字段。与getDeclaredFields()不同,getFields()只返回公共字段,忽略私有字段和受保护字段。同样,这些字段信息也被打印出来。紧接着,代码通过clazz.getDeclaredMethods()获取Student类中声明的所有方法,包括私有方法。这些方法被封装在Method数组中返回。然后,打印出这些方法的信息。clazz.getMethods()方法被调用,返回的是类中所有可访问的公共方法,包括从父类继承的公共方法。与getDeclaredMethods()不同,getMethods()不仅返回类自身的方法,还包括继承的公共方法,并且忽略私有方法和受保护方法。同样,这些信息也被打印出来。最后,通过clazz.getDeclaredConstructors()获取Student类中声明的所有构造器,这些构造器被封装在Constructor数组中返回。然后,打印出这些构造器的信息。clazz.getConstructors()方法返回的是类中所有可访问的公共构造器。与getDeclaredConstructors()不同,getConstructors()只返回公共构造器,忽略私有构造器和受保护构造器。这些构造器的信息也被打印出来。

没有Declared只能获取public的数据,而加上Declared可以获得所有修饰符修饰的数据

单独获取某个属性

下面代码通过Class.forName("Test20250218.Student")加载Student类并获取其Class对象,随后利用反射API动态地访问并展示了该类的字段和方法信息。具体地,它使用getFieldgetDeclaredField方法分别获取了公共字段age和任意访问修饰符的字段heightsexField对象,并打印了这些信息;同时,它使用getDeclaredMethod方法获取了无参方法run、带有Stringint参数的方法run、无参方法getAge以及带有一个String参数的方法getNameStringMethod对象,并同样打印了这些信息

 下面代码首先通过Class.forName("Test20250218.Student")加载了Test20250218.Student类,并获取其Class对象clazz。接着,利用反射API中的getDeclaredConstructor方法,分别获取了Student类中声明的四个不同参数列表的构造方法:第一个构造方法接受Stringintdoublechar四个参数;第二个构造方法接受intdoublechar三个参数;第三个构造方法接受doublechar两个参数;第四个构造方法仅接受一个char参数。每个获取的构造方法都被封装在Constructor对象中,并立即通过System.out.println方法打印出来,展示了Student类中声明的这些构造方法的信息。

类信息的使用

下面代码首先通过Class.forName("Test20250218.Student")加载了Test20250218.Student类,并获取其Class对象clazz。接着,利用反射API中的getDeclaredConstructor方法,首先获取了Student类中声明的无参构造方法,并通过调用newInstance方法创建了Student类的一个实例对象student。然后,获取了接受doublechar两个参数的构造方法,并通过调用newInstance方法并传入参数185.5'男'创建了另一个Student实例对象student1。最后,获取了仅接受一个char参数的构造方法,由于该构造方法可能受到访问修饰符(如private)的限制,因此通过调用setAccessible(true)方法忽略了Java的访问控制检查(即进行了暴力反射),随后调用newInstance方法并传入参数'女'创建了第三个Student实例对象student2

private修饰的数据是在其他类当中访问不到的,所以只能忽略访问权限修饰符的安全检查,

暴力反射针对的就是private修饰的数据

上述代码合集:

package Test20250218;

public class Student {
	//属性
	private String name;
	public int age;
		   double height;
	protected char sex;
	//方法
	private void run(){
		System.out.println("学生跑的很快....");
	}
	public int getAge(){
		return this.age;
	}
	String getNameString(String name) {
		return name;
	}
	protected void run(String a,int b) {
		System.out.println(a+""+b);
	}
	Student(String name,int age,double height,char sex){
		this.name = name;
		this.age = age;
		this.height = height;
		this.sex = sex;
	}
	public Student(int age,double height,char sex){
		this.age = age;
		this.height = height;
		this.sex = sex;
	}
	protected Student(double height,char sex){
		this.height = height;
		this.sex = sex;
	}
	private Student(char sex){
		this.sex = sex;
	}
	Student(){
	}
}
package Test20250218;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
//		//获取类对象
		Class clazz=Class.forName("Test20250218.Student");
//		
//		1
//		Field[] fields =clazz.getDeclaredFields();
//		System.out.println(Arrays.toString(fields));
//		
//		Field[] fields1 = clazz.getFields();
//		System.out.println(Arrays.toString(fields1));
//		
//		//获取方法
//		Method[] methods = clazz.getDeclaredMethods();
//		System.out.println(Arrays.toString(methods));
//		
//		Method[] methods1 = clazz.getMethods();
//		System.out.println(Arrays.toString(methods1));
//		
//		//获取构造器
//		Constructor[] declaredConstructors=clazz.getDeclaredConstructors();
//		System.out.println(Arrays.toString(declaredConstructors));
//		
//		Constructor[] declaredConstructors1=clazz.getConstructors();
//		System.out.println(Arrays.toString(declaredConstructors1));
		
//		2
//		//age是public类型修饰的,那么我们使用getField可以获取到数据,也可以使用
//        //getDeclaredField获取数据
//        Field ageField = clazz.getField("age");
//        System.out.println(ageField);
//
//        Field heightField = clazz.getDeclaredField("height");
//        System.out.println(heightField);
//
//        Field sexField = clazz.getDeclaredField("sex");
//        System.out.println(sexField);
//
//        Method runMethod = clazz.getDeclaredMethod("run");
//        System.out.println(runMethod);
//
//        Method runMethod1 = clazz.getDeclaredMethod("run",String.class,int.class);
//        System.out.println(runMethod1);
//
//        Method getAge = clazz.getDeclaredMethod("getAge");
//        System.out.println(getAge);
//
//        Method getNameString = clazz.getDeclaredMethod("getNameString", String.class);
//        System.out.println(getNameString);
//        System.out.println("--------------------------------");
//
//		3
//        Constructor constructor1 = clazz.getDeclaredConstructor(String.class,int.class,double.class,char.class);
//        System.out.println(constructor1);
//
//        Constructor constructor2 = clazz.getDeclaredConstructor(int.class,double.class,char.class);
//        System.out.println(constructor2);
//
//        Constructor constructor3 = clazz.getDeclaredConstructor(double.class,char.class);
//        System.out.println(constructor3);
//
//        Constructor constructor4 = clazz.getDeclaredConstructor(char.class);
//        System.out.println(constructor4);
		
//		4
//		Constructor constructor=clazz.getDeclaredConstructor();
//		Student student=(Student)constructor.newInstance();
//		
//		Constructor constructor1=clazz.getDeclaredConstructor(double.class,char.class);
//		Student student1=(Student)constructor1.newInstance(185.5,'男');
//		
//		Constructor constructor2=clazz.getDeclaredConstructor(char.class);
//		//private修饰的数据是在其他类当中访问不到的
//		//所以只能忽略访问权限修饰符的安全检查
//		constructor2.setAccessible(true);//暴力反射---------》针对的就是private修饰的数据
//		Student student2=(Student)constructor2.newInstance('女');
		
//		5
//		Constructor constructor=clazz.getDeclaredConstructor();
//		Student student=(Student)constructor.newInstance();
//		//对属性的赋值、取值
//		Field nameField=clazz.getDeclaredField("name");
//		//赋值
//		nameField.setAccessible(true);//暴力反射
//		nameField.set(student,"张三");//set()需要两个参数分别是对象和值
//		System.out.println(nameField.get(student));
//		Field ageField = clazz.getField("age");
//		ageField.set(student,18);
//		System.out.println(ageField.get(student));
//		Field heightField = clazz.getDeclaredField("height");
//		heightField.set(student,185.5);
//		System.out.println(heightField.get(student));
//		Field sexField = clazz.getDeclaredField("sex");
//		sexField.set(student,'女');
//		System.out.println(sexField.get(student));
		
//		6
		Constructor constructor =clazz.getDeclaredConstructor();
		Student student=(Student)constructor.newInstance();
		Method run =clazz.getDeclaredMethod("run");
		run.setAccessible(true);
		run.invoke(student);
		Method getAge =clazz.getDeclaredMethod("getAge");
		getAge.invoke(student);
		Method getStingName = clazz.getDeclaredMethod("getNameString",String.class);
		String name =(String)getStingName.invoke(student,"aaaaa");
		System.out.println(name);
		Method run1=clazz.getDeclaredMethod("run",String.class, int.class);
		run1.invoke(student, "bbbb",99);
	}

}

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

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

相关文章

DeepSeek横空出世,真的拯救了算力焦虑吗?

目录 DeepSeek横空出世,真的拯救了算力焦虑吗? 一、为什么会有算力焦虑 二、来自硅谷四大科技巨头的决策 1、Deepseek在24年底的突然崛起 2、利好算力的大背景下,硅谷四大科技巨头的“落后”加码 3、在算法博弈中加强算力基建的战略 三…

VSCode Error Lens插件介绍(代码静态检查与提示工具)(vscode插件)

文章目录 VSCode Error Lens 插件介绍**功能概述****开发背景****使用方法****适用场景** VSCode Error Lens 插件介绍 功能概述 Error Lens 是一款增强 VS Code 错误提示的扩展工具,通过 内联显示错误和警告信息,直接定位代码问题,提升开发…

网络安全攻防演练——RT实战技巧篇

前言 又是一年hw招聘季,每年hw行动都会吸引大量网络安全从业者参加。同时也会有很多热爱网络安全但无从下手的网安爱好者参与。笔者旨在对网络安全有想法但是没有方向的师傅做一个简单的方向的了解,让师傅有方向去学习。 RT(红队) 1.引入 首先红队的…

[Android] 【汽车OBD软件】Torque Pro (OBD 2 Car)

[Android] 【汽车OBD软件】Torque Pro (OBD 2 & Car) 链接:https://pan.xunlei.com/s/VOIyKOKHBR-2XTUy6oy9A91yA1?pwdm5jm# 获取 OBD 故障代码、汽车性能数据等等。Torque 使用连接到您的 OBD2 发动机管理/ECU 的 OBD II 蓝牙适配器。…

拯救者电脑在重装系统之后电源计划丢失Fn+Q切换不了模式怎么恢复?

参考联想知识库的一下链接: https://iknow.lenovo.com.cn/detail/196192 其中下载的解压文件后的文件需要复制粘贴到D盘的根目录下,再来运行文件。若在生成的log文件中看到导入成功以及控制面板中看到已添加的电源计划即可 如果还是无效可是试试以下的…

sql盲注脚本

在sqli-labs中的第8题无回显可以尝试盲注的手法获取数据 发现页面加载了3秒左右可以进行盲注 布尔盲注数据库名 import requestsdef inject_database(url):datanamefor i in range(1,15):low 32high 128mid (low high) // 2while low < high:path "id1 and asci…

Linux下学【MySQL】常用函数助你成为数据库大师~(配sql+实操图+案例巩固 通俗易懂版~)

绪论​ 每日激励&#xff1a;“唯有努力&#xff0c;才能进步” 绪论​&#xff1a; 本章是MySQL中常见的函数&#xff0c;利用好函数能很大的帮助我们提高MySQL使用效率&#xff0c;也能很好处理一些情况&#xff0c;如字符串的拼接&#xff0c;字符串的获取&#xff0c;进制…

Linux(centos)系统安装部署MySQL8.0数据库(GLIBC版本)

安装前检查服务器glibc版本&#xff0c;下载对应版本包 rpm -qa | grep glibc mysql安装包及依赖包已整理好&#xff0c;下载地址&#xff1a;https://pan.quark.cn/s/3137acc814c0&#xff0c;下载即可安装 一、下载MySQL mysql安装包及依赖包已整理好&#xff0c;下载地址…

Java基于 SpringBoot+Vue的微信小程序跑腿平台V2.0(附源码,文档)

博主介绍&#xff1a;✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不…

git版本控制工具介绍

版本控制 版本控制是软件开发过程中用于管理代码变更的重要手段&#xff0c;它可以记录代码的历史版本&#xff0c;方便开发者进行回溯、协作和问题排查。本地版本控制、集中版本控制和分布式版本控制是三种不同的版本控制模式 本地版本控制 本地版本控制是最基础的版本控制方…

深入解析 vLLM:高性能 LLM 服务框架的架构之美(二)调度管理

深入解析 vLLM&#xff1a;高性能 LLM 服务框架的架构之美&#xff08;一&#xff09;原理与解析 深入解析 vLLM&#xff1a;高性能 LLM 服务框架的架构之美&#xff08;二&#xff09;调度管理 1. vLLM 调度器结构与主要组件 在 vLLM 中&#xff0c;调度器的结构设计围绕任务…

重构测试项目为spring+springMVC+Mybatis框架

重构测试项目为springspringMVCMybatis框架 背景 继上次将自动化测试时的医药管理信息系统项目用idea运行成功后&#xff0c;由于项目结构有些乱&#xff0c;一部分代码好像也重复&#xff0c;于是打算重新重构以下该项目&#xff0c;这次先使用springspringMVCMybatis框架 …

RAGFlow

相关链接 ragflow.io 官网 github 相关术语 RAG “Retrieval-Augmented Generation”&#xff08;RAG&#xff09;是一种结合了检索&#xff08;Retrieval&#xff09;和生成&#xff08;Generation&#xff09;的深度学习模型架构。这种模型通常用于处理自然语言处理&…

java断点调试(debug)

在开发中&#xff0c;新手程序员在查找错误时, 这时老程序员就会温馨提示&#xff0c;可以用断点调试&#xff0c;一步一步的看源码执行的过程&#xff0c;从而发现错误所在。 重要提示: 断点调试过程是运行状态&#xff0c;是以对象的运行类型来执行的 断点调试介绍 断点调试是…

最新智能优化算法: 阿尔法进化(Alpha Evolution,AE)算法求解23个经典函数测试集,MATLAB代码

一、阿尔法进化算法 阿尔法进化&#xff08;Alpha Evolution&#xff0c;AE&#xff09;算法是2024年提出的一种新型进化算法&#xff0c;其核心在于通过自适应基向量和随机步长的设计来更新解&#xff0c;从而提高算法的性能。以下是AE算法的主要步骤和特点&#xff1a; 主…

llama.cpp部署 DeepSeek-R1 模型

一、llama.cpp 介绍 使用纯 C/C推理 Meta 的LLaMA模型&#xff08;及其他模型&#xff09;。主要目标llama.cpp是在各种硬件&#xff08;本地和云端&#xff09;上以最少的设置和最先进的性能实现 LLM 推理。纯 C/C 实现&#xff0c;无任何依赖项Apple 芯片是一流的——通过 A…

国产编辑器EverEdit - 如虎添翼的功能:快速选择

1 快速选择 1.1 应用场景 快速选择适用于批量选择和修改的场景&#xff0c;比如&#xff1a;变量改名。 1.2 使用方法 1.2.1 逐项快速选择 将光标放置在单词前或单词中&#xff0c;选择主菜单查找 -> 快速选择 -> 快速选择或使用快捷键Ctrl D 注&#xff1a;光标放…

基于flask+vue的租房信息可视化系统

✔️本项目利用 python 网络爬虫抓取某租房网站的租房信息&#xff0c;完成数据清洗和结构化&#xff0c;存储到数据库中&#xff0c;搭建web系统对各个市区的租金、房源信息进行展示&#xff0c;根据各种条件对租金进行预测。 1、数据概览 ​ 将爬取到的数据进行展示&#xff…

vue非组件的初学笔记

1.创建Vue实例&#xff0c;初始化渲染的核心 准备容器引包创建Vue实例new Vue() el用来指定控制的盒子data提供数据 2.插值表达式 作用利用表达式插值&#xff0c;将数据渲染到页面中 格式{{表达式}} 注意点 表达式的数据要在data中存在表达式是可计算结果的语句插值表达式…

Spring 事务及管理方式

Spring 事务管理是 Spring 框架的核心功能之一&#xff0c;它为开发者提供了一种方便、灵活且强大的方式来管理数据库事务。 1、事务的基本概念 事务是一组不可分割的操作序列&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部失败回滚&#xff0c;以确保数据的一致…