java内省有什么作用_Java内省
1. 什么是内省?
内省(Introspector)是Java语言对JavaBean类属性、事件的处理方法。
例如类User中有属性name,那么必定有getName,setName方法,我们可以通过他们来获取或者设置值,这是常规操作。
Java提供了一套API来访问某个属性的getter/setter方法,这些API存放在java.beans中。
在计算机科学中,内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。
不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。
内省和反射的区别:
反射是在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。
内省机制是通过反射来实现的,BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性。
我自己的理解是:
内省更多的用在获取属性以及属性的的getter、setter方法,进行一些其他的操作。
反射更多的用在反射创建对象以及调用方法等操作。
2. 内省类库简介
比如User类:
packagecn.qlq;public classUser {private intage;privateString name;privateAddress address;private booleandeleted;public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}publicAddress getAddress() {returnaddress;
}public voidsetAddress(Address address) {this.address =address;
}public booleanisDeleted() {returndeleted;
}public void setDeleted(booleandeleted) {this.deleted =deleted;
}
}classAddress {privateString province;privateString city;publicString getProvince() {returnprovince;
}public voidsetProvince(String province) {this.province =province;
}publicString getCity() {returncity;
}public voidsetCity(String city) {this.city =city;
}
}
主要涉及的类库如下:
(1)Introspector类,可以获取BeanInfo类,常见的使用方法如下:(重要)
BeanInfo beanInfo =Introspector.getBeanInfo(user.getClass());//第二个参数代表停止的类,也就是如果有继承关系不获取第二个参数及其父类的信息
BeanInfo beanInfo2 = Introspector.getBeanInfo(user.getClass(), Object.class);
(2)BeanInfo类:通过上面的内省类获得 (重要)
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);
作用1:获取BeanDescriptor一个全局的类描述信息
//获取BeanDescriptor-一个全局的类描述信息
BeanDescriptor beanDescriptor =beanInfo.getBeanDescriptor();
System.out.println(beanDescriptor);
作用2:获取所有的PropertyDescriptor属性描述器(如果获取BeanInfo的时候第二个参数没传会获取从Object继承的信息)
private static void testBeanInfo2(User user) throwsException {
BeanInfo beanInfo= Introspector.getBeanInfo(user.getClass(), Object.class);//获取PropertyDescriptor描述器
PropertyDescriptor[] propertyDescriptors =beanInfo.getPropertyDescriptors();for(PropertyDescriptor propertyDescriptor : propertyDescriptors) {//获取属性类型
Class> propertyType =propertyDescriptor.getPropertyType();//获取属性名称
String name =propertyDescriptor.getName();//获取属性的读方法,getXXX
Method readMethod =propertyDescriptor.getReadMethod();//获取属性的写方法,setXXX
Method writeMethod =propertyDescriptor.getWriteMethod();
System.out.println(name);
System.out.println(propertyType);
System.out.println(readMethod.getName());
System.out.println(writeMethod.getName());
System.out.println("==============");
}
}
结果:
address
class cn.qlq.Address
getAddress
setAddress
==============
age
int
getAge
setAge
==============
deleted
boolean
isDeleted
setDeleted
==============
name
class java.lang.String
getName
setName
==============
作用3: 获取MethodDescriptor描述器(如果获取BeanInfo的时候第二个参数没传会获取从Object继承的方法)
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);//获取MethodDescriptor描述器
MethodDescriptor[] methodDescriptors =beanInfo.getMethodDescriptors();for(MethodDescriptor methodDescriptor : methodDescriptors) {
Method method=methodDescriptor.getMethod();
System.out.println(method);
}
结果:
public java.lang.String cn.qlq.User.getName()
public void cn.qlq.User.setAge(int)
public void cn.qlq.User.setName(java.lang.String)
public int cn.qlq.User.getAge()
public boolean cn.qlq.User.isDeleted()
public cn.qlq.Address cn.qlq.User.getAddress()
public void cn.qlq.User.setAddress(cn.qlq.Address)
public void cn.qlq.User.setDeleted(boolean)
作用4:获取EventSetDescriptor(这个不常用)
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);//获取EventSetDescriptor描述器
EventSetDescriptor[] eventSetDescriptors =beanInfo.getEventSetDescriptors();for(EventSetDescriptor eventSetDescriptor : eventSetDescriptors) {
System.out.println(eventSetDescriptor);
}
(3)BeanDescriptor 一个全局的Bean描述信息,一般没啥用
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);//获取BeanDescriptor-一个全局的类描述信息
BeanDescriptor beanDescriptor =beanInfo.getBeanDescriptor();
System.out.println(beanDescriptor);
(4)PropertyDescriptor 属性描述器,可以获取到属性名称、属性的get方法以及set方法,进而做到修改方法。
其获取方式可以通过BeanInfo获取,也可以通过直接new的方式获取。
方式一:
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);//获取PropertyDescriptor描述器
PropertyDescriptor[] propertyDescriptors =beanInfo.getPropertyDescriptors();for(PropertyDescriptor propertyDescriptor : propertyDescriptors) {//获取属性类型
Class> propertyType =propertyDescriptor.getPropertyType();//获取属性名称
String name =propertyDescriptor.getName();//获取属性的读方法,getXXX
Method readMethod =propertyDescriptor.getReadMethod();//获取属性的写方法,setXXX
Method writeMethod =propertyDescriptor.getWriteMethod();
System.out.println(name);
System.out.println(propertyType);
System.out.println(readMethod.getName());
System.out.println(writeMethod.getName());
System.out.println("==============");
}
方式二:通过直接new的方式
User user = newUser();
user.setName("zhangsan");
PropertyDescriptor propertyDescriptor= new PropertyDescriptor("name", User.class);//获取getter方法读取属性
Method readMethod =propertyDescriptor.getReadMethod();
Object invoke=readMethod.invoke(user);
System.out.println(invoke);//获取setter方法修改属性
Method writeMethod =propertyDescriptor.getWriteMethod();
writeMethod.invoke(user,"lisi");
System.out.println(user.getName());
结果:
zhangsan
lisi
如果属性不存在会报错如下:
Exception in thread "main" java.beans.IntrospectionException: Method not found: isNamess
at java.beans.PropertyDescriptor.(PropertyDescriptor.java:107)
at java.beans.PropertyDescriptor.(PropertyDescriptor.java:71)
at cn.qlq.Client.main(Client.java:14)
(5) MethodDescriptor 方法描述器,可以获取方法的名称、Method等信息
其获取方式可以通过BeanInfo获取
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);//获取MethodDescriptor描述器
MethodDescriptor[] methodDescriptors =beanInfo.getMethodDescriptors();for(MethodDescriptor methodDescriptor : methodDescriptors) {
System.out.println(methodDescriptor);
Method method=methodDescriptor.getMethod();
}
3. 内省的应用
采用内省实现的JavaBean转Map和List转List、Map转Bean、Maps转Beans、实现将1个bean的属性赋值给另1个bean(属性拷贝)
packagecn.qs.utils;importjava.beans.BeanInfo;importjava.beans.Introspector;importjava.beans.PropertyDescriptor;importjava.lang.reflect.Method;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importorg.apache.commons.lang3.ArrayUtils;public classBeanUtils {/*** 内省进行数据转换-javaBean转map
*
*@paramobj
* 需要转换的bean
*@return转换完成的map
*@throwsException*/
public static Map beanToMap(T obj, boolean putIfNull) throwsException {
Map map = new HashMap<>();//获取javaBean的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass(), Object.class);//获取属性描述器
PropertyDescriptor[] propertyDescriptors =beanInfo.getPropertyDescriptors();for(PropertyDescriptor propertyDescriptor : propertyDescriptors) {//获取属性名
String key =propertyDescriptor.getName();//获取该属性的值
Method readMethod =propertyDescriptor.getReadMethod();//通过反射来调用javaBean定义的getName()方法
Object value =readMethod.invoke(obj);if (value == null && !putIfNull) {continue;
}
map.put(key, value);
}returnmap;
}public static List> beansToMaps(List objs, boolean putIfNull) throwsException {return beansToMaps(objs, putIfNull, false);
}public static List> beansToMaps(List objs, boolean putIfNull, booleanaddIndex)throwsException {
List> result = new ArrayList<>();
Map beanToMap = null;int index = 0;for(Object obj : objs) {
beanToMap=beanToMap(obj, putIfNull);if(addIndex) {
beanToMap.put("index", ++index);
}
result.add(beanToMap);
}returnresult;
}/*** Map转bean
*
*@parammap
* map
*@paramclz
* 被转换的类字节码对象
*@return*@throwsException*/
public static T map2Bean(Map map, Class clz) throwsException {//new 出一个对象
T obj =clz.newInstance();//获取person类的BeanInfo对象
BeanInfo beanInfo = Introspector.getBeanInfo(clz, Object.class);//获取属性描述器
PropertyDescriptor[] propertyDescriptors =beanInfo.getPropertyDescriptors();for(PropertyDescriptor propertyDescriptor : propertyDescriptors) {//获取属性名
String key =propertyDescriptor.getName();
Object value=map.get(key);//通过反射来调用Person的定义的setName()方法
Method writeMethod =propertyDescriptor.getWriteMethod();
writeMethod.invoke(obj, value);
}returnobj;
}public static List maps2Beans(List> maps, Class clz) throwsException {
List result = new ArrayList<>();for (Mapmap : maps) {
result.add(map2Bean(map, clz));
}returnresult;
}/*** 复制origin的值到dest上
*
*@paramdest
* 目标对象
*@paramorigin
* 元对象
*@paramsetNull
* 如果源对象属性为null是否拷贝
*@paramexcludeFieldNames
* 排除的属性*/
public static void copyProperties(T dest, T origin, booleansetNull, String[] excludeFieldNames) {try{//获取person类的BeanInfo对象
BeanInfo destBeanInfo = Introspector.getBeanInfo(dest.getClass(), Object.class);//获取目标属性描述器
PropertyDescriptor[] destBeanInfoPropertyDescriptors =destBeanInfo.getPropertyDescriptors();for(PropertyDescriptor propertyDescriptor : destBeanInfoPropertyDescriptors) {//获取属性名
String key =propertyDescriptor.getName();if(ArrayUtils.contains(excludeFieldNames, key)) {continue;
}//获取该属性的值
Method readMethod =propertyDescriptor.getReadMethod();//如果源对象没有对应属性就跳过
Object srcValue = null;try{
srcValue=readMethod.invoke(origin);
}catch(Exception ignored) {//ignored
continue;
}//如果源对象的值null且null不设置的时候跳过
if (srcValue == null && !setNull) {continue;
}//获取setter方法修改属性
Method writeMethod =propertyDescriptor.getWriteMethod();
writeMethod.invoke(dest, srcValue);
}
}catch(Exception ignored) {//ignored
}
}public static voidcopyProperties(T dest, T origin) {
copyProperties(dest, origin,false, null);
}
}
总结:
如果通过BeanInfo操作属性的话,一般需要过滤掉Object继承的东西,也就是获取BeanInfo的时候如下:
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);
java内省有什么作用_Java内省相关推荐
- java内省和反射机制_Java内省和反射机制三步曲之 - 内省
经过多方面的资料搜集整理,写下了这篇文章,本文主要讲解java的反射和内省机制,希望对大家有点帮助,也希望大家提出不同的看法! 1).内省(Introspector)是 Java 语言对 Bean 类 ...
- java类与对象作用_Java类与对象
●类和对象的关系: 一:类是对同一类事物(对象)的抽象,对象实际存在的该类的各种实体. 二:面向对编程的核心:找合适的对象来做合适的事. 三:Java中找到对象: 1):sun自己定义好的类,必须知道 ...
- java 代码块的作用_Java核心(三):代码块的作用
Java中用{ }括起来的代码段就是代码块,他分为如下几种类型 位置 作用 局部代码块 在方法当中使用,作用是控制变量的生命周期. 局部代码块的变量,只能在代码块内部使用,在执行结束后会被Java回收 ...
- java 中gui的作用_java学习中最应该注意的Java GUI用户界面以何为基础
java中的GUI编程(Graphic User Interface,图形用户接口),是在它的笼统窗(Abstract Window Toolkit,AWT)上完成的,java.awt是AWT的东西类 ...
- java volatile关键字的作用_java volatile关键字作用及使用场景详解
1. volatile关键字的作用:保证了变量的可见性(visibility).被volatile关键字修饰的变量,如果值发生了变更,其他线程立马可见,避免出现脏读的现象.如以下代码片段,isShut ...
- java中flush函数作用_Java语言中flush()函数作用及使用方法详解
最近在学习io流,发现每次都会出现flush()函数,查了一下其作用,起作用主要如下 //------–flush()的作用--------– 笼统且错误的回答: 缓冲区中的数据保存直到缓冲区满后才写 ...
- java 注解处理器的作用_Java注解处理器
Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...
- java中result的作用_JAVA中的Resultset
JAVA中的Resultset (2012-04-21 14:53:34) 标签: it JAVA中Resultset是一个类 . 结果集(ResultSet)是数据中查询结果返回的一种对象,可以说结 ...
- java的复合语句的作用_Java复合语句的使用方法详解
与 C 语言及其他语言相同, Java 语言的复合语句是以整个块区为单位的语句,所以又称为块语句.下面我们来看看有关复合语句的使用方法和实例. 复合语句由开括号"{"开始,闭括号& ...
最新文章
- SQL SERVER特殊行转列案列一则
- 数学基础学习随笔--序言
- 8个字典常用的内置函数,一次性给你总结了!
- 返回值是内置类型 不能更改_选择通过更改内容类型返回的详细程度,第二部分...
- shell编程题(三)
- 文本聚类分析算法_聚类分析算法综述
- Qt resizeEvent 控件居中设置
- Go-fastdfs分布式文件系统搭建
- 软考 系统分析师教程 免费拿走不谢
- ARKit入门到精通-1.5 -基础内容-史小川-专题视频课程
- 区块链技术之P2P网络(一)
- fiddler Android下https抓包全攻略
- 【词性标注】一篇文章弄懂词性标注
- 【定量分析、量化金融与统计学】R语言方差分析的outliers陷阱
- 定时器输出的PWM频率范围及占空比精度
- 【题解】【循环】幂级数求和
- matlab错误dparsfa,Dpabi安装出错,求助大大佬
- 渲染效果图哪家好?2022最新实测(三)
- 开发者福利chatGPT软件Build Software. Fast.
- 【邮政编码识别】基于计算机视觉实现邮政编码识别含Matlab源码