Java内省详解

  内省和反射有什么区别:

  反射式在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。 
  内省机制是通过反射来实现的,BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性。

  1.通过PropertyDescriptor修改属性方式

 1 public class BeanInfoUtil {
 2     public static void setProperty(UserInfo userInfo,String userName)throws Exception{
 3         PropertyDescriptor propDesc=new PropertyDescriptor(userName,UserInfo.class);
 4         Method methodSetUserName=propDesc.getWriteMethod();
 5         methodSetUserName.invoke(userInfo, "wong");
 6         System.out.println("set userName:"+userInfo.getUserName());
 7     }
 8
 9     public static void getProperty(UserInfo userInfo,String userName)throws Exception{
10         PropertyDescriptor proDescriptor =new PropertyDescriptor(userName,UserInfo.class);
11         Method methodGetUserName=proDescriptor.getReadMethod();
12         Object objUserName=methodGetUserName.invoke(userInfo);
13         System.out.println("get userName:"+objUserName.toString());
14     }
15
16 }  

  2.通过Introspector类修改属性

 1 public class BeanInfoUtil2 {
 2     public static void setPropertyByIntrospector(UserInfo userInfo,
 3             String userName) throws Exception {
 4
 5         BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);
 6         PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();
 7         if (proDescrtptors != null && proDescrtptors.length > 0) {
 8             for (PropertyDescriptor propDesc : proDescrtptors) {
 9                 if (propDesc.getName().equals(userName)) {
10                     Method methodSetUserName = propDesc.getWriteMethod();
11                     methodSetUserName.invoke(userInfo, "alan");
12                     System.out
13                             .println("set userName:" + userInfo.getUserName());
14                     break;
15                 }
16             }
17         }
18     }
19
20     public static void getPropertyByIntrospector(UserInfo userInfo,
21             String userName) throws Exception {
22         BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);
23         PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();
24         if (proDescrtptors != null && proDescrtptors.length > 0) {
25             for (PropertyDescriptor propDesc : proDescrtptors) {
26                 if (propDesc.getName().equals(userName)) {
27                     Method methodGetUserName = propDesc.getReadMethod();
28                     Object objUserName = methodGetUserName.invoke(userInfo);
29                     System.out
30                             .println("get userName:" + objUserName.toString());
31                     break;
32                 }
33             }
34         }
35     }
36
37 }  

  注意事项,在上述修改JavaBean属性的时候,如果数据类型不对的话,会报错。例如BeanInfoUtil.setProperty(userInfo, “age”);报错是应为age属性是int数据类型,而setProperty方法里面默认给age属性赋的值是String类型。所以会爆出argument type mismatch参数类型不匹配的错误信息。 
  为了解决上述问题,Apache开发了一套简单、易用的API来操作Bean的属性——BeanUtils工具包。

  

public static void main(String[] args) throws Exception {
        Point point = new Point(2, 5);
        String proName = "x";
        BeanUtils.setProperty(point, proName, "8");
        System.out.println(point.getX());// 8
        System.out.println(BeanUtils.getProperty(point, proName));// 8
        System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());// java.lang.String     

        BeanUtils.setProperty(point, proName, 8);
       System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());// java.lang.String
   }
   //我们看到虽然属性x的类型是Integer,但是我们设置的时候无论是Integer还是String,BeanUtils的内部都是当成String来处理的。  

  BeanUtils支持javabean属性的级联操作;

 1 public static void main(String[] args) throws Exception {
 2     Point point = new Point(2, 5);//在point中加一个属性 private Date birth = new Date();并产生setter/getter方法
 3     String proName = "birth";
 4     Date date= new Date();
 5     date.setTime(10000);
 6     BeanUtils.setProperty(point, proName, date);
 7     System.out.println(BeanUtils.getProperty(point, proName));
 8
 9     BeanUtils.setProperty(point, "birth.time", 10000);
10     System.out.println(BeanUtils.getProperty(point, "birth.time"));//10000
11 }
12 //之所以可以 BeanUtils.setProperty(point, "birth.time", 10000);这样写,那是因为Date类中有getTime()和setTime()方法,即Date类中相当于有time这个属性。   

  BeanUtils和PropertyUtils对比:

 1 public static void main(String[] args) throws Exception {
 2     Point point = new Point(2, 5);
 3     String proName = "x";
 4     BeanUtils.setProperty(point, proName, "8");
 5     System.out.println(BeanUtils.getProperty(point, proName));//8
 6     System.out.println(BeanUtils.getProperty(point, proName).getClass().getName());//java.lang.String
 7
 8 // PropertyUtils.setProperty(point, proName, "8");//exception:argument type mismatch
 9     PropertyUtils.setProperty(point, proName, 8);
10     System.out.println(PropertyUtils.getProperty(point, proName));//8
11     System.out.println(PropertyUtils.getProperty(point, proName).getClass().getName());//java.lang.Integer
12 }
13 //BeanUtils它以字符串的形式对javabean进行转换,而PropertyUtils是以原本的类型对javabean进行操作。如果类型不对,就会有argument type mismatch异常。  

  理解了相应的原理,那些现成的工具用起来就会更舒服,如Beanutils与 PropertyUtils工具。这两个工具设置属性的时候一个主要区别是PropertyUtils.getPropety方法获得的属性值的类型为该 属性本来的类型,而BeanUtils.getProperty则是将该属性的值转换成字符串后才返回。

时间: 2024-10-19 15:01:46

Java内省详解的相关文章

package-info.java文件详解

package-info.java文件详解 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.pacakge-info.java介绍 pacakge-info.java是一个Java文件,可以添加到任何的Java源码包中.pacakge-info.java的目标是提供一个包级的文档说明或者是包级的注释. pacakge-info.java文件中,唯一要求包含的内容是包的声明语句,比如: package com.ch.service; 二.包文档 在

java 反射 详解

本文来自:blog.csdn.net/ljphhj JAVA反射机制:   通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没用,下面我们看看实践 Demo - Demo: package cn.lee.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import

Java synchronized详解

Java synchronized详解 第一篇: 使用synchronized 在编写一个类时,如果该类中的代码可能运行于多线程环境下,那么就要考虑同步的问题.在Java中内置了语言级的同步原语--synchronized,这也大大简化了Java中多线程同步的使用.我们首先编写一个非常简单的多线程的程序,是模拟银行中的多个线程同时对同一个储蓄账户进行存款.取款操作的. 在程序中我们使用了一个简化版本的Account类,代表了一个银行账户的信息.在主程序中我们首先生成了1000个线程,然后启动它们

Java虚拟机详解——JVM常见问题总结

[正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考之前的系列文章,尤其是那篇:Java虚拟机详解04--GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾回收.类加载机制. 先把本文的目录画一个思维导图:(图的源文件在本文末尾) 一.Java引用的四种状态: 强引用:  用的最广.我们平时写代码时,new一个Object存放在堆内存,然后用一个引用指向它,这就是强引用. * 如果一个对象具有强引用,那垃圾回收器绝不会回收它*.当内存空间不足,Java虚拟机宁

Java引用类型详解

JVM  的垃圾回收器对于不同类型的引用有不同的处理方式.java中对于一个对象来说,只要有引用的存在,它就会一直存在于内存中.如果这样的对象越来越多,超出了JVM中的内存总数,JVM就会抛出OutOfMemory错误.虽然垃圾回收的具体运行是由JVM来控制的,但是开发人员仍然可以在一定程度上与垃圾回收器进行交互,其目的在于更好的帮助垃圾回收器管理好应用的内存.这种交互方式就是使用JDK1.2 引入的  java.lang.ref包. 强引用(strong reference) 在一般的 Jav

Java堆栈详解 .

1. Java中堆栈(stack)和堆(heap) (1)内存分配的策略 按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的. 静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不 允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的

Java网络详解

Java网络详解 Java网络基本概念 网络基础知识 1.计算机网络形式多样,内容繁杂.网络上的计算机要互相通信,必须遵循一定的协议.目前使用最广泛的网络协议是Internet上所使用的TCP/IP协议 2.网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯.网络编程中有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上

Java面向对象详解

Java面向对象详解 前言:接触项目开发也有很长一段时间了,最近开始萌发出想回过头来写写以前学 过的基础知识的想法.一是原来刚开始学习接触编程,一个人跌跌撞撞摸索着往前走,初学的时候很多东西理解的也懵懵懂懂,后来实践的多了,有些东西才慢慢清 楚:二是经过一定的实践之后,反过头来再去学习一些基础东西才能够理解的更透彻:三是有些东西基础但是确很重要,是值得好好搞一搞的. 1.面向对象 面向对象(Object Oriented)是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),

Java反射详解

Java反射详解 分类:java, 基础日期:2012-07-20作者:ticmy 19 反射,是Java中非常重要的一个功能,如果没有反射,可以说很多框架都难以实现. 什么是反射?说白了就是可以通过Java代码获取装载到方法区的类信息的手段. 当装载一个类时,会在方法区产生一个数据结构,该结构中包含着装载的类的相关信息.字节码可以看成是数据流,那么方法区的这种数据结构可以说是字节码数据流的结构化表现.装载的最终产物就是java.lang.Class类的一个对象,它是Java程序与方法区内部数据