Java的内省技术

2023-11-19

什么是内省

在计算机科学中,内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。 不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。

内省和反射的区别

反射是在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。
.
内省(IntroSpector)是Java 语言针对 Bean 类属性、事件的一种缺省处理方法。 JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。内省机制是通过反射来实现的,BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性。
在这里插入图片描述
在Java内省中,用到的基本上就是上述几个类。

通过BeanInfo这个类就可以获取到类中的方法和属性。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。

Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中,

一般的做法是通过类 Introspector 的 getBeanInfo方法 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法,这就是内省机制。

实例

自定义一个bean类:

/**
 * 
 */
package beanutils;

import java.util.Date;

/**
 * JavaBean
 *
 */
public class Person {
	private String name;// 字段
	private String password;
	private int age;
	private Date birthday;

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public String getAb() { // ab也是bean中的一个属性!
		return null;

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

使用内省API操作bean的属性

/**
 * 
 */
package cn.itcast.introspector;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * 使用内省API操作bean的属性
 *
 */
public class Demo1 {
	// 1.得到bean的所有属性
	@Test
	public void test1() throws Exception {
		BeanInfo info = Introspector.getBeanInfo(Person.class, Object.class);// 不自省从父类继承的属性
		PropertyDescriptor[] pds = info.getPropertyDescriptors();// 取得属性描述器
		for (PropertyDescriptor pd : pds) {
			System.out.println(pd.getName());
		}
	}

	// 2.操纵bean的指定属性:age
	@Test
	public void test2() throws Exception {
		Person p = new Person();

		PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);

		// 得到属性的写方法,为属性赋值
		Method method = pd.getWriteMethod(); // setAge
		method.invoke(p, 24);

		// 获取属性的值
		method = pd.getReadMethod(); // getAge()
		System.out.println(method.invoke(p, null));
	}
	
	// 3.获取当前操作的属性的类型
		@Test
		public void test3() throws Exception {
			Person p = new Person();

			PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);
			System.out.println(pd.getPropertyType());
			
		}
}

以上的操作略显繁琐,Apache组织开发了一套用于操作JavaBean的API——beanutils,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。

beanutils工具包

BeanUtils工具包的下载地址:http://commons.apache.org/beanutils/;注意:BeanUtils的包依赖于logging包,logging包的下载地址为:http://commons.apache.org/logging/。

在工程下新建lib目录,导入commons-beanutils-1.9.3.jar 和支持包commons-logging-1.2.jar
选中两个包,右键build path/add to build path
在这里插入图片描述
Beanutils工具包的常用类和方法:

  • BeanUtils
  • PropertyUtils
  • ConvertUtils.regsiter(Converter convert, Class clazz)

对bean中的某个属性进行赋值

下面的例子test1(),直接通过BeanUtils类的setProperty方法来对bean中的某个属性进行赋值。

@Test
	public void test1() throws IllegalAccessException, InvocationTargetException {

		Person p = new Person();
		BeanUtils.setProperty(p, "name", "yaoer");

		System.out.println(p.getName());
	}

在这里插入图片描述

自定义转换器

下面的test2,演示了如何自定义一个转换器。
因为用户提交的"1994-10-12"是个字符串,而bean中的birthday是个Date类型的属性,由于这套API中,String类型自动转化仅限于8种基本类型,所以无法直接将字符串转换为Date。这就需要我们自定义一个转换器。
重点:ConvertUtils.regsiter(Converter convert, Class clazz)方法。

@Test

	public void test2() throws IllegalAccessException, InvocationTargetException {
		Person p = new Person();
		// 模拟用户提交的表单
		String name = "yaoer";
		String password = "123";
		String age = "24";
		String birthday = "1994-10-12";

		// 给beanUtils注册一个日期转换器
		ConvertUtils.register(new Converter() {

			public Object convert(Class type, Object value) {

				if (value == null) {
					return null;
				}
				if (!(value instanceof String)) {
					throw new ConversionException("只支持String类型的转换哦!");

				}
				String str = (String) value;
				if (str.trim().equals("")) {
					return null;
				}

				SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
				try {
					return df.parse(str);
				} catch (ParseException e) {
					throw new RuntimeException(e); // 异常链不能断
				}

			}
		}, Date.class);

		// 封装到p对象中

		BeanUtils.setProperty(p, "name", name);
		BeanUtils.setProperty(p, "password", password);
		BeanUtils.setProperty(p, "age", age); // 自动将数据转换(基本类型)
		BeanUtils.setProperty(p, "birthday", birthday);

		System.out.println(p.getName());
		System.out.println(p.getPassword());
		System.out.println(p.getAge());
		System.out.println(p.getBirthday());

	}

在这里插入图片描述
如图,成功转换。
需要注意的一点是Date的导包,import java.util.Date是正确的,而不是sql的,否则会报错。

import java.util.Date;

使用API中自带的转换器:DateLocaleConverter

@Test
	public void test3() throws  ConversionException, IllegalAccessException, InvocationTargetException{
		Person p = new Person();
		// 模拟用户提交的表单
		String name = "yaoer";
		String password = "123";
		String age = "24";
		String birthday = "1994-10-12";

		ConvertUtils.register(new DateLocaleConverter(), Date.class);

		BeanUtils.setProperty(p, "name", name);
		BeanUtils.setProperty(p, "password", password);
		BeanUtils.setProperty(p, "age", age); // 自动将数据转换(基本类型)
		BeanUtils.setProperty(p, "birthday", birthday);

		System.out.println(p.getName());
		System.out.println(p.getPassword());
		System.out.println(p.getAge());
		Date date = p.getBirthday();
		System.out.println(date.toString());

	}

本例运行时报错,暂时还未找到原因。
在这里插入图片描述

用map集合中的值填充bean的属性

@Test
	public void test4() throws IllegalAccessException, InvocationTargetException {
		// TODO Auto-generated method stub
		Map map = new HashMap();
		map.put("name","zhuzhu");
		map.put("password","123");
		map.put("age","24");
		map.put("birthday","1994-10-12");
		
		ConvertUtils.register(new DateLocaleConverter(), Date.class);
		Person bean = new Person();
		BeanUtils.populate(bean, map);//用map集合中的值填充bean的属性
		
		System.out.println(bean.getName());
		System.out.println(bean.getPassword());
		System.out.println(bean.getAge());
		System.out.println(bean.getBirthday());
		
	}

由于同样使用了DateLocaleConverter,所以和上例报了同样的错误。
如果将转换器替换为test2例子中自定义的转换器,那么可以成功通过测试:
在这里插入图片描述

总结

内省是基于反射实现的,主要用来操作JavaBean,通过内省可以很方便的动态获得bean的set/get方法,属性,方法名。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java的内省技术 的相关文章

  • 在java中轮询Http服务器(重复发送http get请求)

    当对其进行 REST 调用时 我的 Web 服务器会发送一些信息 我想不断轮询该服务器 间隔5秒后重复发送HTTP GET请求 以检查返回的信息是否有任何变化 做到这一点最有效的方法是什么 您能提供一些代码示例吗 请注意 我只想开发客户端代
  • 按下按钮并在java中的新窗口中打开文件

    我创建了一个 JFrame 并放置了一个文本字段和按钮 在文本字段中我放置了从文本文件读取的名称 我知道我想单击按钮并打开一个已知窗口 我想在其中放置名称 其他信息来自同一个文件 这是我的代码 这是我的主框架 package Fronten
  • Netbeans 8.1 Gnome 3 GTK+ UI 字体和选项卡高度

    我刚刚在运行 GNOME 3 桌面的 Ubuntu 16 04 上安装了 NetBeans 8 1 如果可能的话 我想继续使用 IDE 的 GTK 外观和感觉 但 UI 上的字体 尤其是选项卡中的字体 太小且重叠 我尝试添加 fontsiz
  • 有没有创建 Cron 表达式的 Java 代码? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要一个 Java 代码来根据用户输入创建一个 cron 表达式 用户输入是时间 频率和执行次数 只需从评论中添加 自己创建 即可
  • 垃圾收集器如何在幕后工作来收集死对象?

    我正在阅读有关垃圾收集的内容 众所周知 垃圾收集会收集死亡对象并回收内存 我的问题是 Collector 如何知道任何对象已死亡 它使用什么数据结构来跟踪活动对象 我正在研究这个问题 我发现GC实际上会跟踪活动对象 并标记它们 每个未标记的
  • Java 的支持向量机?

    我想用Java编写一个 智能监视器 它可以随时发出警报detects即将到来的性能问题 我的 Java 应用程序正在以结构化格式将数据写入日志文件
  • Android:文本淡入和淡出

    我已阅读此 stackoverflow 问题和答案 并尝试实现文本淡入和淡出 Android中如何让文字淡入淡出 https stackoverflow com questions 8627211 how to make text fade
  • 如何在 Java 中向时间戳添加/减去时区偏移量?

    我正在使用 JDK 8 并且玩过ZonedDateTime and Timestamp很多 但我仍然无法解决我面临的问题 假设我得到了格式化的Timestamp在格林威治标准时间 UTC 我的服务器位于某处 假设它设置为Asia Calcu
  • Jframe 内有 2 个 Jdialogs 的 setModal 问题

    当我设置第一个选项时 我遇到了问题JDialog模态 第二个非模态 这是我正在尝试实现的功能 单击 测试对话框 按钮 一个JDialog有名字自定义对话框 主要的将会打开 如果单击 是 选项自定义对话框主 其他JDialog named 自
  • java inputstream 打印控制台内容

    sock new Socket www google com 80 out new BufferedOutputStream sock getOutputStream in new BufferedInputStream sock getI
  • Runtime.exec 处理包含多个空格的参数

    我怎样才能进行以下运行 public class ExecTest public static void main String args try Notice the multiple spaces in the argument Str
  • 如何检查某个元素是否存在于一组项目中?

    In an ifJava中的语句如何检查一个对象是否存在于一组项目中 例如 在这种情况下 我需要验证水果是苹果 橙子还是香蕉 if fruitname in APPLE ORANGES GRAPES Do something 这是一件非常微
  • 提高 PostgreSQL 1 亿数据左连接查询性能

    我在用Postgresql 9 2 version Windows 7 64 bit RAM 6GB 这是一个Java企业项目 我必须在我的页面中显示订单相关信息 有三个表通过左连接连接在一起 Tables TV HD 389772 行 T
  • 蓝牙发送和接收文本数据

    我是 Android 开发新手 我想制作一个使用蓝牙发送和接收文本的应用程序 我得到了有关发送文本的所有内容逻辑工作 但是当我尝试在手机中测试它时 我看不到界面 这是Main Activity Code import android sup
  • 如何将 HTML 链接放入电子邮件正文中?

    我有一个可以发送邮件的应用程序 用 Java 实现 我想在邮件中放置一个 HTML 链接 但该链接显示为普通字母 而不是 HTML 链接 我怎样才能将 HTML 链接放入字符串中 我需要特殊字符吗 太感谢了 Update 大家好你们好 感谢
  • 使用 Elastic Beanstalk 进行 Logback

    我在使用 Elastic Beanstalk 记录应用程序日志时遇到问题 我正在 AWS Elastic Beanstalk 上的 Tomcat 8 5 with Corretto 11 running on 64bit Amazon Li
  • Spring @Cacheable 和 @Async 注解

    我需要缓存一些异步计算的结果 具体来说 为了克服这个问题 我尝试使用 Spring 4 3 缓存和异步计算功能 作为示例 我们采用以下代码 Service class AsyncService Async Cacheable users C
  • partitioningBy 必须生成一个包含 true 和 false 条目的映射吗?

    The 分区依据 https docs oracle com javase 8 docs api java util stream Collectors html partitioningBy java util function Pred
  • 抛出 Java 异常时是否会生成堆栈跟踪?

    这是假设我们不调用 printstacktrace 方法 只是抛出和捕获 我们正在考虑这样做是为了解决一些性能瓶颈 不 堆栈跟踪是在构造异常对象时生成的 而不是在抛出异常对象时生成的 Throwable 构造函数调用 fillInStack
  • Spring RESTful控制器方法改进建议

    我是 Spring REST 和 Hibernate 的新手 也就是说 我尝试组合一个企业级控制器方法 我计划将其用作未来开发的模式 您认为可以通过哪些方法来改进 我确信有很多 RequestMapping value user metho

随机推荐

  • 机器学习实战项目总结

    1 预测模型新项目模板 机器学习是针对数据进行自动挖掘 找出数据的内在规律 并应用这个规律来预测新数据 一个很好的实践机器学习项目的方法 使用从UCI机器学习仓库链接 获取的数据集开启一个机器学习项目 分类或回归模型的机器学习项目可以分成以
  • Linux Nginx配置静态html

    Linux Nginx配置静态html 第一次接触服务器时 对项目部署和域名部署感觉很新鲜 有意思 很神奇 开始学习Nginx配置静态的HTML 使用工具 MobaXterm CHS exe 第一步 将html的项目放入服务器 将自己做好的
  • 【华为OD机试真题 JAVA】信道分配

    JS版 华为OD机试真题 JS 信道分配 标题 信道分配 时间限制 1秒 内存限制 262144K 语言限制 不限 算法工程师小明面对着这样一个问题 需要将通信用的信道分配给尽量多的用户 信道的条件及分配规则如下 1 所有信道都有属性 阶
  • origin中把多个拟合曲线放在一张图

    双击其中一个 或者New一个graph 这里直接双击其中一个图 右键 找到layer contents 可以看到 一个scatter配一个polynomial fit line 把剩下的B C D对应的点和拟合曲线添加进去 注意 这里的pl
  • 01、Java并发 Java ExecutorService

    ExecutorService 是 Java java util concurrent 包的重要组成部分 是 Java JDK 提供的框架 用于简化异步模式下任务的执行 一般来说 ExecutorService 会自动提供一个线程池和相关
  • 程序员如何做副业?35岁前,千万别让死工资绊住你赚钱的步伐

    近年来互联网行情下降 好多人都在思考要不要搞个副业来抵御风险 这不又来事了 这两天又爆了互联网大裁员 继阿里 向社会输送人才 之后 京东又搞了个 毕业礼 整的小伙伴们人心惶惶 副业的关注度又一波升级 那今天我们就来聊聊 程序员做副业这件事
  • cef编译

    按照大神的一遍过 具体过程非常详细 链接https kefong blog csdn net article details 119908780 spm 1001 2101 3001 6650 2 utm medium distribute
  • 《C++ Primer(第5版)》学习笔记(第5章)

    第5章 语句 C 提供了条件执行语句 循环语句和用于中断当前控制流的跳转语句 本章将具体介绍这些语句 5 1 简单语句 空语句 最简单的语句是空语句 只有一个单独的分号 如在程序的某个地方语法上需要一条语句但是逻辑上不需要 此时应该使用空语
  • 透过Python 将接收邮件邮件进行分类统计

    工作的需要自行学习了Python的一些功能 将所学的经验在这里分享给大家 文章目录 目录 文章目录 前言 一 环境准备 二 使用步骤 1 引入库 2 读入数据 总结 前言 工作中我们可能会透过邮件 让其他公司收集资料 在学会Python之前
  • 全网最最最轻量级检测网络 yolo-fastest 快速上手

    文章目录 0x01 Yolo Fastest 0x02 Prepare step1 clone step2 make step3 run darknet 0x03 Train step1 获取权重文件 step2 准备数据集 step3 修
  • 成功上岸字节35K,技术4面+HR面,耗时20天,真是不容易

    这次字节的面试 给我的感触很深 意识到基础的重要性 一共经历了五轮面试 技术4面 HR面 下面看正文 本人自动专业毕业 压抑了五个多月 终于鼓起勇气 去字节面试 下面是我的面试过程 很多面试题 都是靠记忆写的 希望能帮助到大家 致那些努力的
  • 初步认识操作系统(Operator System)

    操作系统 一 冯诺依曼体系结构 内存的重要作用 二 操作系统的概念 三 设计操作系统的目的 三 操作系统在计算机体系中的定位 四 操作系统是如何进行管理的 一 冯诺依曼体系结构 在众多计算机相关的书籍中 不得不提的就是冯诺依曼体系结构 冯诺
  • 无需魔法三分钟上线Midjourney应用,【附源码】【示例】

    ps 我是标题党 目前还没见过三分钟完成任务的 三分钟只能打通Midjourney接口 我花了一天时间接入应用哈哈哈 首先 我要感谢laf赞助我 让我可以免费使用Midjourney进行开发和测试 来自白嫖党的快乐 其次 我要感谢白夜 米开
  • Linux驱动编程(总线设备驱动模型)

    一 驱动编写的3种方法 1 传统写法 使用哪个引脚 怎么操作引脚 都写死在代码中 最简单 不考虑扩展性 可以快速实现功能 修改引脚时 需要重新编译 2 总线设备驱动模型 引入 platform device platform driver
  • 最近opencv又报了啥错(一)

    前言 别骂了别骂了 太久没打python 手贼生 最近在搞opencv和一些ocr 报了一堆错 有些是python的原生错误 有的是opencv的 有的是我nt 就全部记录一下吧 1 bad argument type for built
  • 端口监控信息

    netstat nlptu grep 8080 一 0 0 0 0 8080 代表8080端口 对内网和外网都是开放的 tcp 0 0 0 0 0 0 8080 0 0 0 0 LISTEN 123941 java 二 查看网卡的代码 da
  • KVM中使用usb设备

    进来学习usb驱动 看到网上都在分析usb skeleton c的驱动框架 就想对其调试一下 看一下其函数调用流程 要想调试usb skeleton 首先需要kvm能够探测到usb设备 其次 在kvm中编译usb skeleton c 最后
  • 深度学习要学多久?半年能入门深度学习吗?

    深度学习的学习时间因个人背景 目标和学习方法而异 不同人可能需要不同的时间来掌握深度学习 深度学习要学多久 通常情况下 入门深度学习可能需要几个月的时间 如果你已经有相关背景知识 学习进度可能会更快 以下是一些因素 可以影响学习深度学习所需
  • 解一元二次方程-Java语言实现

    前言 高考完的那个暑假我就开始自学C语言 那时候通过看视频和 C primer plus 写了一个解一元二次方程的程序 从此走上了吊打大学同班同学的路 但是那次是用C语言写的 如今白云苍狗 我已经不是曾经的那个我了 但我还是一如既往的废物
  • Java的内省技术

    什么是内省 在计算机科学中 内省是指计算机程序在运行时 Run time 检查对象 Object 类型的一种能力 通常也可以称作运行时类型检查 不应该将内省和反射混淆 相对于内省 反射更进一步 是指计算机程序在运行时 Run time 可以