Java重点:反射机制的使用

news2024/12/22 20:57:52

目录

一、概念

二、类类

1、类类的获取方式

1)类名.Class

2)对象.getClass()

3)Class.forName()

三、反射实例化

1、调用一个公有的无参构造方法

2、调用一个公有的一个参构造方法

3、调用一个公有的两个参构造方法

4、调用一个私有的一个参构造方法

四、反射:方法调用

1、公有无参

2、公有有参

3、私有有参

完整代码:

五、反射:读写属性


一、概念

J2EE中的反射(Reflection)是指在程序运行期间访问、检测和修改自身的状态或行为。通过反射,可以动态地获取一个类的所有成员变量、方法、构造函数等信息,并且可以在运行时调用这些成员。在J2EE中,反射可以方便实现一些框架ORM工具,以及其他动态性要求的应用程序。

什么是反射?

反射(Reflection)是一种在运行时动态地获取和操作对象的能力,它允许程序通过对象的类类型来了解对象的成员和方法,并且可以在运行时调用这些成员和方法。反射可以用于许多目的,例如在运行时动态加载类、实例化对象、查看和修改对象的属性和方法、调用私有方法和构造函数,等等。在Java中,反射通过java.lang.reflect包中的类和接口来实现。反射的优点是可以使我们的代码更加灵活和动态,但是反射的开销比较大,因此在性能要求较高的情况下,应该谨慎使用。

总的来说:反射Java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法

二、类类

在Java反射(reflection)中,Class类被称为“类类”(class of class),因为它代表了JVM中的一个类。每个Java类在内存中都有一个对应的Class类实例对象,可以通过Java的反射机制获取。通过这个实例,我们可以动态地获取创建操作一个类的各种元数据(如属性、方法、注解等),并可以在程序运行时动态地创建、修改该类的对象。通过反射,我们可以实现更加灵活和动态的编程方式,可以在编码阶段不确定访问的类和方法,直到运行时才确定需要获取和调用的类和方法。

1、类类的获取方式

1. Object类中的getClass()方法:可以获取一个对象所属的类。

2. 类名.class:直接通过类名这种语法形式获取一个类的Class实例对象

3. Class.forName(String className):过类的全限定名获取Class实例对象,需要处理ClassNotFoundException异常。

这些方式均可以获得一个Java类的Class实例对象,从而可以利用反射机制获取该类的一系列信息,如属性、方法、构造方法、注解等。

1)类名.Class

在开始示例的前期准备工作我们写一个类(Class)

package com.tgq.reflect;

/**
 * 一个类
 * 
 * @author tgq
 *
 */
public class Student {
	private String sid;

	private String sname;

	public Integer age;

	static {
		System.out.println("加载进jvm中!");
	}

	public Student() {
		super();
		System.out.println("调用无参构造方法创建了一个学生对象");
	}

	public Student(String sid) {
		super();
		this.sid = sid;
		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
	}

	public Student(String sid, String sname) {
		super();
		this.sid = sid;
		this.sname = sname;
		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
	}

	@SuppressWarnings("unused")
	private Student(Integer age) {
		System.out.println("调用Student类私有的构造方法创建一个学生对象");
		this.age = age;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public void hello() {
		System.out.println("你好!我是" + this.sname);
	}

	public void hello(String name) {
		System.out.println(name + "你好!我是" + this.sname);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}
}

编写好一个类之后我们开始调用方法进行拿去:代码示例

package com.tgq.reflect;

/**
 * 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
 * 
 * @author tgq
 *
 */
public class Demo_01 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {

		// 1、类名.Class
		Class c1 = Student.class;
		System.out.println(c1);

	}
}

输出结果:

2)对象.getClass()

package com.tgq.reflect;

/**
 * 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
 * 
 * @author tgq
 *
 */
public class Demo_01 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {

		// 1、类名.Class
		// Class c1 = Student.class;
		// System.out.println(c1);
		
		// 2、对象.getClass();
		Student student = new Student();
		Class c2 = student.getClass();
		System.out.println(c2);

	}
}

输出结果:

3)Class.forName()

package com.tgq.reflect;

/**
 * 类类的获取方式: 1、类名.Class 2、对象.getClass(); 3、Class.forName();
 * 
 * @author tgq
 *
 */
public class Demo_01 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {

		// 1、类名.Class
		// Class c1 = Student.class;
		// System.out.println(c1);

		// 2、对象.getClass();
		// Student student = new Student();
		// Class c2 = student.getClass();
		// System.out.println(c2);

		// 3、Class.forName();
		Class c3 = Class.forName("com.tgq.reflect.Student");
		System.out.println(c3);
	}
}

输出结果:

三、反射实例化

在Java中,可以使用反射来实例化一个类。具体实现可以通过Class类的newInstance()方法或者Constructor类的newInstance()方法来实现。

三个常用的方法:getConstructor ()getDeclaredConstructor () ,newInstance()

一切的反射从类类开始

1、调用一个公有的无参构造方法

public class Demo_02 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		// 一切反射从类类开始
		// 不管是哪一种获取类类的方法都是可以的
		// Class c1 = Class.forName("com.tgq.reflect.Student");
		// Student student = new Student();
		// Class c1 = student.getClass();
		Class c1 = Student.class;
		/*
		 * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
		 */
		Student stu1 = (Student) c1.newInstance();
		System.out.println(stu1);


	}
}

输出结果:

2、调用一个公有的一个参构造方法

public class Demo_02 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		// 一切反射从类类开始
		// 不管是哪一种获取类类的方法都是可以的
		// Class c1 = Class.forName("com.tgq.reflect.Student");
		// Student student = new Student();
		// Class c1 = student.getClass();
		Class c1 = Student.class;
		/*
		 * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
		 */
		Student stu1 = (Student) c1.newInstance();
		System.out.println(stu1);

		/*
		 * 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
		 * 
		 * parameterTypes:代表了参数的类别Class
		 */
		Constructor con1 = c1.getConstructor(String.class);
		Student stu2 = (Student) con1.newInstance("s1");
		System.out.println(stu2);

		

	}
}

输出结果:

3、调用一个公有的两个参构造方法

public class Demo_02 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		// 一切反射从类类开始
		// 不管是哪一种获取类类的方法都是可以的
		// Class c1 = Class.forName("com.tgq.reflect.Student");
		// Student student = new Student();
		// Class c1 = student.getClass();
		Class c1 = Student.class;
		/*
		 * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
		 */
		Student stu1 = (Student) c1.newInstance();
		System.out.println(stu1);

		/*
		 * 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
		 * 
		 * parameterTypes:代表了参数的类别Class
		 */
		Constructor con1 = c1.getConstructor(String.class);
		Student stu2 = (Student) con1.newInstance("s1");
		System.out.println(stu2);

		/*
		 * 3、调用两个参数的构造器实例化
		 */
		Constructor con2 = c1.getConstructor(String.class, String.class);
		Student stu3 = (Student) con2.newInstance("s1", "sb");
		System.out.println(stu3);

	}
}

输出结果:

4、调用一个私有的一个参构造方法

public class Demo_02 {
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		// 一切反射从类类开始
		// 不管是哪一种获取类类的方法都是可以的
		// Class c1 = Class.forName("com.tgq.reflect.Student");
		// Student student = new Student();
		// Class c1 = student.getClass();
		Class c1 = Student.class;
		/*
		 * 1、调用一个无参构造器反射实例化: 如果没有无参构造器是会报错的
		 */
		Student stu1 = (Student) c1.newInstance();
		System.out.println(stu1);

		/*
		 * 调用有参构造器必须要实例化构造器对象 2、调用一个有一个参数的构造器:getConstructor == 获取构造器对象
		 * 
		 * parameterTypes:代表了参数的类别Class
		 */
		Constructor con1 = c1.getConstructor(String.class);
		Student stu2 = (Student) con1.newInstance("s1");
		System.out.println(stu2);

		/*
		 * 3、调用两个参数的构造器实例化
		 */
		Constructor con2 = c1.getConstructor(String.class, String.class);
		Student stu3 = (Student) con2.newInstance("s1", "sb");
		System.out.println(stu3);

		/*
		 * 4、调用一个私有的带一个参数的构造器实例化: getConstructor只能获取公有的构造器对象
		 *
		 * getDeclaredConstructor:获取私有的构造器对象
		 */
		Constructor con3 = c1.getDeclaredConstructor(Integer.class);
		// 打开私有的访问权限
		con3.setAccessible(true);
		Student stu4 = (Student) con3.newInstance(1);
		System.out.println(stu4);

	}
}

输出结果:

四、反射:方法调用

1、公有无参

public class Demo_03 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;
		// 1、反射调用 无参方法
		Student s = (Student) c.newInstance();
		// 反射调用无参方法,先获取到方法对象
		// name:方法名
		// parameterTypes:调用这个方法要传的参数类型
		Method m1 = c.getMethod("hello");
		// invoke:方法的返回值
		// obj:类示例
		// args:参数值
		Object invoke = m1.invoke(s);
		System.out.println(invoke);

		
	}
}

输出结果:

2、公有有参

public class Demo_03 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;
		// 1、反射调用 无参方法
		Student s = (Student) c.newInstance();
		// 反射调用无参方法,先获取到方法对象
		// name:方法名
		// parameterTypes:调用这个方法要传的参数类型
		Method m1 = c.getMethod("hello");
		// invoke:方法的返回值
		// obj:类示例
		// args:参数值
		Object invoke = m1.invoke(s);
		System.out.println(invoke);

		// 2、调用有参方法
		Method m2 = c.getMethod("hello", String.class);
		Object invoke2 = m2.invoke(s, "asdfghjk");
		System.out.println(invoke2);

	}
}

输出结果:

3、私有有参

public class Demo_03 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;
		// 1、反射调用 无参方法
		Student s = (Student) c.newInstance();
		// 反射调用无参方法,先获取到方法对象
		// name:方法名
		// parameterTypes:调用这个方法要传的参数类型
		Method m1 = c.getMethod("hello");
		// invoke:方法的返回值
		// obj:类示例
		// args:参数值
		Object invoke = m1.invoke(s);
		System.out.println(invoke);

		// 2、调用有参方法
		Method m2 = c.getMethod("hello", String.class);
		Object invoke2 = m2.invoke(s, "asdfghjk");
		System.out.println(invoke2);


		// 3、调用有参私有的方法
		Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
		// 打开私有权限
		m3.setAccessible(true);
		Object invoke3 = m3.invoke(s, 1, 2);
		System.out.println(invoke3);
	}
}

输出结果:

完整代码:

package com.tgq.reflect;

import java.lang.reflect.Method;

/**
 * 反射动态方法的调用
 * 
 * @author tgq
 *
 */
public class Demo_03 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;
		// 1、反射调用 无参方法
		Student s = (Student) c.newInstance();
		// 反射调用无参方法,先获取到方法对象
		// name:方法名
		// parameterTypes:调用这个方法要传的参数类型
		Method m1 = c.getMethod("hello");
		// invoke:方法的返回值
		// obj:类示例
		// args:参数值
		Object invoke = m1.invoke(s);
		System.out.println(invoke);

		// 2、调用有参方法
		Method m2 = c.getMethod("hello", String.class);
		Object invoke2 = m2.invoke(s, "asdfghjk");
		System.out.println(invoke2);


		// 3、调用有参私有的方法
		Method m3 = c.getDeclaredMethod("add", Integer.class, Integer.class);
		// 打开私有权限
		m3.setAccessible(true);
		Object invoke3 = m3.invoke(s, 1, 2);
		System.out.println(invoke3);
	}
}

五、反射:读写属性

通过Field类的get()set()方法来实现。

拿到我们所有的属性:


public class Demo_04 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;

		Student stu = new Student("1", "1A");
		// 我们把age设置一个值
		stu.age = 18;
		// System.out.println(stu.getSid());
		
		// 获取对象中全部的属性
		Field[] fields = c.getDeclaredFields();
		// 遍历
		for (Field f : fields) {
			// 因为sid、sname是私有的,所以我们要打开私有权限
			f.setAccessible(true);
			// 获取所有属性
			System.out.println(f.getName() + ":" + f.get(stu));
		}

	}
}

输出结果:

我们进行设置属性值:


public class Demo_04 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;

		Student stu = new Student("1", "1A");
		// 我们把age设置一个值
		stu.age = 18;
		// System.out.println(stu.getSid());

		// 拿到属性
		Field snamefield = c.getDeclaredField("sname");
		// 打开权限
		snamefield.setAccessible(true);
		// 进行设置
		snamefield.set(stu, "2B");
		
		// 获取对象中全部的属性
		Field[] fields = c.getDeclaredFields();
		// 遍历
		for (Field f : fields) {
			// 因为sid、sname是私有的,所以我们要打开私有权限
			f.setAccessible(true);
			// 获取所有属性
			System.out.println(f.getName() + ":" + f.get(stu));
		}

	}
}

输出结果:

完整代码:

package com.tgq.reflect;

import java.lang.reflect.Field;

/**
 * 反射:读写属性
 * 
 * @author tgq
 *
 */
public class Demo_04 {
	public static void main(String[] args) throws Exception {
		Class c = Student.class;

		Student stu = new Student("1", "1A");
		// 我们把age设置一个值
		stu.age = 18;
		// System.out.println(stu.getSid());

		// 拿到属性
		Field snamefield = c.getDeclaredField("sname");
		// 打开权限
		snamefield.setAccessible(true);
		// 进行设置
		snamefield.set(stu, "2B");

		// 获取对象中全部的属性
		Field[] fields = c.getDeclaredFields();
		// 遍历
		for (Field f : fields) {
			// 因为sid、sname是私有的,所以我们要打开私有权限
			f.setAccessible(true);
			// 获取所有属性
			System.out.println(f.getName() + ":" + f.get(stu));
		}

	}
}

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

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

相关文章

gitee(码云)如何生成并添加公钥

一,简介 在使用Gitee的时候,公钥是必须的,无论是克隆还是上传。本文主要介绍如何本地生成和添加公钥到服务器。供参考。 二,步骤介绍 2.1 本地生成公钥 打开git bash 输入以下代码回车三次: # 替换为你自己的邮箱…

opencv特征检测 HOG特征算法

1 HOG特征简介 Hog 算法的工作原理是创建图像中梯度方向分布的柱状图,然后以一种非常特殊的方式对其进行归一化。这种特殊的归一化使得Hog 能够有效地检测物体的边缘,即使在对比度很低的情况下也是如此。这些标准化的柱状图被放在一个特征向量&#xff…

51单片机的数字时钟系统【含仿真+程序+报告】

51单片机的数字时钟系统【含仿真程序报告】 1、 系统组成2、功能概述3、仿真4、程序代码5、报告6、资源链接 1、 系统组成 该系统由AT89C51单片机DS1302时钟模块按键模块DS18B20LCD显示模块构成。 2、功能概述 可显示实时的日期 包括 年-月-日 时分秒 星期 农历时间DS18B20室…

将图像2D转换为3D--LeiaPix Converter

LeiaPix Converter是一款免费的在线图像处理工具,可帮助用户将2D图像实时转换为精美的3D光场图像。 它使用由Leia开发的专有算法,为照片、插画和艺术作品等2D图像添加深度和立体感,目前是完全免费的。 LeiaPix Converter 的特点 多格式转换…

安全多方计算、联邦学习和可信执行环境

目录 隐私计算的三大技术流派:联邦学习、安全多方计算、可信计算 隐私计算的三大技术流派:联邦学习、安全多方计算、可信计算 1.多方安全计算,由姚期智院士于1982年首次提出,通过设计特殊的加密算法和协议,在无可信第…

Java 已知文件路径参数,用两种方法获取文件名

一、先获取带扩展名的fileName String filePath "D:\\manage\\uploadFile\\2023-06-28283\\初测.xlsx"; File file new File(filePath); // 或者 Path path Paths.get(filePath);String fileName1 file.getName(); System.out.println(fileName1);Path fileName…

Jmeter线程组配置

目录 前言: 一、线程组配置字段说明 二、线程组配置示例 前言: JMeter是一款开源的压力测试工具,被广泛应用于测试Web应用程序的性能和负载能力。其中线程组是JMeter中最基本、最重要的功能之一。线程组用于模拟多个并发用户对目标应用程…

Bryntum Scheduler Pro 5.3.5 Crack-专业调度组件

BRYNTUM Scheduler Pro调度程序专业版 专业的日程安排小部件 一个专业有大脑的调度UI组件。Scheduler Pro 可帮助您安排任务,同时考虑资源和任务的可用性。 连接您的任务 让 Scheduler Pro 处理剩下的事情。它将根据您定义的链接安排您的任务并遵守任何任务限制。这…

echarts——折线图点击线触发函数getZr()——技能提升

今天看到技术群里在讨论echarts中的折线图,有人遇到一个功能就是点击折线要触发点击事件,但是官网上的click点击事件只针对折线的拐点。 但是有人提出是可以通过getZr()方法来实现 网上也确实有大神提出一样的解决方法,链接如下&#xff1…

属鸡的脾气性格怎么样?

有的人认为属鸡的人脾气暴躁,而有的认为属鸡的人性格温和, 其实属鸡的人都有两面性,对好人善良温情,对坏人则腹黑邪恶,是不是很惊讶?古人认为鸡有预报能力,此种预言能力在鸡年生的人身上也会出现…

Stable Diffusion 使用outpainting扩展图像

通常SD可以应用绘制的图像是固定分辨率的,但是如果想要超出这个分辨率的话那就要使用一些方法,并且如果还想保持这些图片的连贯性,例如背景就要使用到outpainting。 文章目录 操作流程准备图像 操作流程 准备图像 首先将需要扩展边缘的图像…

能查看历史记录的好用的笔记app是哪款?

当我回顾自己经常做笔记的习惯时,我发现一个问题困扰着我:如何方便地查看和管理历史记录?因为对于我这样一个频繁记录学习和工作笔记的人来说,回顾过去的记录是一种宝贵的学习和反思机会。能查看历史记录的好用的笔记app是哪款&am…

Junit基本使用

文章目录 0. 了解Junit51. 注解2. 断言3. 用例执行顺序4. 测试套件(Suite)5.参数化 0. 了解Junit5 Java版本最低要求为8。Junit是一个开源的java语言的单元测试框架。java方向使用最广泛的单元测试框架。使用java开发者都应当学习Junit并且掌握单元测试…

CDH 之 Sentry 安装失败 Unable to find the MySQL JDBC driver

安装报错如下: 详细日志: Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driverat com.cloudera.cmf.service.hive.HiveMetastoreDbUtil.countTables(HiveMetastoreDbUtil.java…

stm32GPIO点亮led的小发现

偶然发现点亮led的小困惑,现在解决了。我们知道stm32中,GPIO端口的内部一般是接高电平(3.3v),其外部就是我们肉眼所看到的PA1等标号。 1、写法一 led的正极接3.3v,这样当A1引脚输出低电平0(即GPIO_ResetBi…

vs中编译时出现error LNK1104: 无法打开文件*.exe

因为此时有一个VS工程在运行了,将其关闭就可以了。 参考:vs中编译时出现error LNK1104: 无法打开文件*.exe

云原生|kubernetes|centos7下的kubeadm部署的集群内在线部署kubesphere(外部etcd)

前言: 本文将主要就在centos7操作系统下已有的一个利用kubeadm部署的集群内在线安装kubesphere做一个介绍,该kubernetes集群是使用的etcd外部集群。 kubernetes集群的搭建本文不做过多介绍,具体的搭建流程见我的博客: 云原生|k…

卷积层|Convolution|知识补充

CNN中增加了Convolution层和Pooling层; CNN中层的连接顺序是“Convolution-ReLu-Pooling”。 全连接层存在的问题: 数据的形状被“忽视”了,比如,输入的数据是一个三维的图像信息,但是在向全连接层输入时,…

【样式 支付下单 弹窗】静态页面,订单结算,确认支付,付款,收款方式

效果图展示 uview 2.0 uniapp <template><view class""><u-popup :show"show" close"close" :round"10" closeable :closeOnClickOverlayfalse><view class"pop"><view class"title&q…

CB2401与RFX2401C的兼容区别对比

PIN TO PIN直接兼容RFX2401C的单片射频收发芯片&#xff0c;可支持BT、BLE、ZIGBEE、ISM 2.4G非标协议。CB2401架构集成了 PA、LNA、发送和接收开关电路&#xff0c;输出功率和通信频道可以通过程序进行配置。 由于该芯片有非常优越的性能&#xff0c;高灵敏度和效率&#xff0…