java内省

本文介绍了JavaBean的概念,如何通过属性的getter和setter方法实现数据封装,以及使用内省技术操作JavaBean属性的方法。此外,还介绍了第三方工具BeanUtils的使用,包括其常用类和方法,以及如何方便地操作JavaBean属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1、首先了解JavaBean

  JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类的方法主要用于访问私有的字段。

例:写一个JavaBean

package com.itheima.introspector;

public class Person {

private String name;//定义一个name字段

private String sex;//定义一个sex字段

private int age;//定义一个age字段

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

  在实际开发中,用户把大量的数据提交过来,我们需要用面向对象的思想去接收,把这些数据封装到一个对象中,这样的类就可以称作JavaBean

2、什么是Java对象的属性和属性的读写方法

  上面的Person对象中有三个字段,但此时不能称他们为属性,这些字段只有对外提供了gettersetter方法才能称作属性,就是说一个Bean的属性不是有上面的字段决定的,是有他们的gettersetter方法决定的。

如果上面的Person类添加代码如下

public String getAddress(){

return null;

}

请问现在Person类中一共有多少属性

通过思考,我们知道一共有五个属性,分别为:name,sex,age,address,class(继承Object)

3、内省(Introspector

 3.1、我们为什么学内省

  我们知道在开发框架时,经常需要使用java对象的属性来封装程序中的数据,每次都使用反射技术完成此类操作比较麻烦,所以sun公司开发了一套API,专门用来操作java对象的属性。

3.2、内省访问JavaBean属性的两种方法

(1)通过PropertyDescriptor类操作Bean的属性

(2)通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法

方法一:通过第一种方法来操作Person的属性

package com.itheima.introspector;

import java.beans.IntrospectionException;

import java.beans.PropertyDescriptor;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import org.junit.Test;

public class IntrospectorDemo {

@Test

public void test()throws Exception {

// 创建一个Person对象

Person p = new Person();

Object value="黑马_1";

String propertyName="name";

//调用写方法,往对象中封转值

setProperty(p, propertyName, value);

//从对象中取出属性的值

// 得到p对象的属性描述器

Object retVal = getProperty(p, propertyName);

System.out.println(retVal);

}

//获取属性的读

private Object getProperty(Person obj, String propertyName)

throws IntrospectionException, IllegalAccessException,

InvocationTargetException {

// 得到p对象的属性描述器

PropertyDescriptor pd=new PropertyDescriptor(propertyName, obj.getClass());

//得到属性的写方法

Method m=pd.getReadMethod();

//执行方法

Object retVal=m.invoke(obj);

return retVal;

}

    //获取属性的写方法

private void setProperty(Object p, String propertyName, Object value)

throws IntrospectionException, IllegalAccessException,

InvocationTargetException {

// 得到p对象的属性描述器

PropertyDescriptor pd=new PropertyDescriptor(propertyName, p.getClass());

//得到属性的写方法

Method m=pd.getWriteMethod();

//调用invoke方法执行

m.invoke(p,value);

}

}

运行结果:黑马_1

  从上面的程序中我们可以看出利用属性描述器PropertyDescriptor,很容易对属性进行读和写的操作

方法二:

package com.itheima.introspector;

import java.beans.BeanInfo;

import java.beans.IntrospectionException;

import java.beans.Introspector;

import java.beans.PropertyDescriptor;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import org.junit.Test;

public class IntrospectorDemo1 {

@Test

public void test()throws Exception {

// 创建一个Person对象

Person p = new Person();

Object value="黑马_1";

String propertyName="name";

//调用写方法,往对象中写数据

setPerproty(p, propertyName, value);

Object retVal = getProperty(p, propertyName);

System.out.println(retVal);

}

//获取属性的读

private Object getProperty(Object obj, String propertyName)

throws IntrospectionException, IllegalAccessException,

InvocationTargetException {

//首先通过Introspector中的getBeanInfo方法创建一个BeanInfo对象

BeanInfo info=Introspector.getBeanInfo(obj.getClass());

//然后调用BeanInfo中的方法得到所有的属性,然后

PropertyDescriptor[]pds=info.getPropertyDescriptors();

//利用增强for循环遍历

Object retVal=null;

for(PropertyDescriptor pd:pds){

//如果正在操作的属性等于了指定的那个属性

if(pd.getName().equals(propertyName)){

//调用写方法

Method m=pd.getReadMethod();

    retVal=m.invoke(obj);

break;

}

}

return retVal;

}

 //获取属性的写方法

private void setPerproty(Object obj, String propertyName, Object value)

throws IntrospectionException, IllegalAccessException,

InvocationTargetException {

//首先通过Introspector中的getBeanInfo方法创建一个BeanInfo对象

BeanInfo info=Introspector.getBeanInfo(obj.getClass());

//然后调用BeanInfo中的方法得到所有的属性,然后

PropertyDescriptor[]pds=info.getPropertyDescriptors();

//利用增强for循环遍历

for(PropertyDescriptor pd:pds){

//如果正在操作的属性等于了指定的那个属性

if(pd.getName().equals(propertyName)){

//调用写方法

Method m=pd.getWriteMethod();

m.invoke(obj, value);

break;

}

}

}

}

运行结果:黑马_1

  从两个方法对比可以看出,第一种方法操作很方便,用的地方也很多,但是它只能操作一个属性,第二种方法操作比较复杂,它没有提供操作一个属性的方法,只提供了操作所有属性的方法。

4、第三方的工具:BeanUtils

  我们知道,在实际应用中操作javabean属性的几率非常的高,利用上述的两种方法都非常的麻烦,所有有人写出了一个工具包,可以很方便的操作JavaBean的属性了。

在用BeanUtils之前首先需要将相关的开发包导入到我们的开发环境中去,主要有两个包如下:

(1)commons-beanutils-1.8.0.jar

(2)Commons-logging.jar

4.1BeanUtils工具包中常用的类

(1)BeanUtils

(2)Properties

(3)ConvertUtils.regsiter(Converter convert, Class clazz)

(4)自定义转换器

1BeanUtils类的主要方法

1public static void setProperty(Object bean, String name,Object value)

  向bean中的指定属性添加值

2public static String getProperty(Object bean,String name)

  获取某个指定属性的值

例:

package com.itheima.introspector;

import org.apache.commons.beanutils.BeanUtils;

import org.junit.Test;

public class BeanUtilsDemo1 {

@Test

public void test1()throws Exception{

//创建一个Person对象

Person p=new Person();

//设置Person的name属性

BeanUtils.setProperty(p, "name","黑马_1");

//获取Person的name属性的值

String name=BeanUtils.getProperty(p, "name");

System.out.println(name);

}

}

运行结果:黑马_1

例二:

package com.itheima.introspector;

import org.apache.commons.beanutils.BeanUtils;

import org.junit.Test;

public class BeanUtilsDemo1 {

@Test

public void test1()throws Exception{

String name="黑马_1";

String sex="男";

String age="23";

//创建一个Person对象

Person p=new Person();

BeanUtils.setProperty(p, "name",name);//向p中设置name属性

BeanUtils.setProperty(p, "sex",sex);//向p中设置sex属性

BeanUtils.setProperty(p, "age",age);//向p中设置age属性

System.out.println(BeanUtils.getProperty(p, "name"));

System.out.println(BeanUtils.getProperty(p, "sex"));

System.out.println(BeanUtils.getProperty(p, "age"));

}

}

运行结果:黑马_1

          男

          23

 但是对上面的程序有一个疑问,在Person中我们定义的age的类型为int,而我们测试的时候明明String age=”23”;,为什么能够运行成功的。  

  这个问题就涉及到了BeanUtils中的类型转换器了,Beanutils中内置了8中基本数据类型的类型转换器,可以自动的进行数据类型的转换,但是如果是别的类型,就会出现错误,如下代码:

  在Person中加如下代码

private Date birthday;//定义一个Date类型的属性

public Date getBirthday() {

return birthday;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

如果这样设置属性

String birthday=1999-11-10;

BeanUtils.setProperty(p, "birthday",birthday)

就会出现类型转换异常的错误,这是因为Date没有在Beanutils中设置它的类型的转换,要想运行成功,需要注册一个自定义的转换器

ConvertUtils类的register方法

(5)ConvertUtils.regsiter(Converter convert, Class clazz)

上面的代码加如下代码:

//为了让日期赋值到bean中的birthday属性上,我们被beanutils注册一个日期转换器

ConvertUtils.register(new Converter() {

@Override

public Object convert(Class type, Object value) {

//判断value是否为null

if(value==null){

return null;

}

    //首先判断value是否为String类型的

if(!(value instanceof String))//如果不是String类型抛出异常

 throw new ConversionException("只支持String类型的转换");

String str=(String)value;

if(str.trim().equals("")){

return null;

}

//创建SimpleDateFormart对象

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");

try {

return sdf.parse(str);//转换类型

catch (ParseException e) {

throw new RuntimeException(e);

}

}

}, Date.class);

通过上面的注册类型转换器,就可以正常的运行了

黑马_1

23

Wed Nov 10 00:00:00 GMT 1999

  这样的类型转换器用处非常的广泛,以后我们学习框架的时候例如Struts1,Struts2时,就需要利用类型转换器了。

BeanUtilsMap集合的应用。

public static void populate(Object bean, Map properties)

Map集合中数据填充到bean

例:

@Test

public void test2()throws Exception{

Map map=new HashMap();//创建一个Map集合

map.put("name""黑马_2");//向集合中添加元素

map.put("sex""男");//向集合中添加元素

map.put("age""23");//向集合中添加元素

map.put("birthday""1999-11-10");//向集合中添加元素

Person p=new Person();

//为了让日期赋值到bean中的birthday属性上,我们被beanutils注册一个日期转换器

ConvertUtils.register(new Converter() {

@Override

public Object convert(Class type, Object value) {

//判断value是否为null

if(value==null){

return null;

}

    //首先判断value是否为String类型的

if(!(value instanceof String))//如果不是String类型抛出异常

 throw new ConversionException("只支持String类型的转换");

String str=(String)value;

if(str.trim().equals("")){

return null;

}

//创建SimpleDateFormart对象

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");

try {

return sdf.parse(str);//转换类型

catch (ParseException e) {

throw new RuntimeException(e);

}

}

}, Date.class);

//把Map集合中数据填充到对象p中

BeanUtils.populate(p, map);

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

System.out.println(p.getSex());

System.out.println(p.getAge());

System.out.println(p.getBirthday());

}

这样我们就把map集合中的数据填充到了person对象中,这在javaWeb中会经常的用到。例如我们通过request传递的数据通常会放到map集合中,所以我们能够通过这个方法把map集合中的数据填充到bean中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值