一、概念
Java Reflection Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
Java反射机制提供的功能 :
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
生成动态代理
二、反射相关的主要API:
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造方法 。。。
三、Class 类
对照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
Class本身也是一个类 Class 对象只能由系统建立对象 一个类在 JVM 中只会有一个Class实例 一个Class对象对应的是一个加载到JVM中的一个.class文件 每个类的实例都会记得自己是由哪个 Class 实例所生成 通过Class可以完整地得到一个类中的完整结构
方法名 | 功能说明 |
static Class forName(String name) | 返回指定类名 name 的 Class 对象 |
Object newInstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class [] getInterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Class getSuperclass() | 返回表示此Class所表示的实体的超类的Class |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Field[] getDeclaredFields() | 返回Field对象的一个数组 |
Method getMethod(String name,Class … paramTypes) | 返回一个Method对象,此对象的形参类型为paramType |
四、实例化Class类对象(四种方法)
)前提:若已知具体的类,通过类的class属性获取,该方法 最为安全可靠,程序性能最高
实例:Class clazz = String.class; Class cls = int.Type;
2)前提:已知某个类的实例,调用该实例的getClass()方法获 取Class对象
实例:String s = "": Class cls = s.getClass();
3)前提:已知一个类的全类名,且该类在类路径下,可通过 Class类的静态方法forName()获取,可能抛ClassNotFoundException 实例:Class clazz = Class.forName(“java.lang.String”);
4)其他方式(不做要求) ClassLoader cl = this.getClass().getClassLoader(); Class clazz4 = cl.loadClass(“类的全类名”);
@Test
public void test3() throws ClassNotFoundException, IOException {
ClassLoader load1 = ClassLoader.getSystemClassLoader();
System.out.println(load1);//sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader load2 = load1.getParent();
System.out.println(load2); //sun.misc.Launcher$ExtClassLoader@54bedef2
ClassLoader load3 = load2.getParent();
System.out.println(load3);//null
String clasName = "java.lang.String";
Class<?> forName = Class.forName(clasName);
ClassLoader load4 = forName.getClassLoader();
System.out.println(load4);//sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader classLoader = this.getClass().getClassLoader();
System.out.println(classLoader);
Class<?> aClass = classLoader.loadClass("com.atguigu.reflect.Person");
System.out.println(aClass);
//掌握加载配文文件
ClassLoader classLoader1 = this.getClass().getClassLoader();
FileInputStream ins = new FileInputStream(new File("jdbc.peoperties"));
InputStream in = classLoader1.getResourceAsStream("com\\atguigu\\reflect\\jdbc.properties");
Properties p = new Properties();
p.load(in);
String user = p.getProperty("user");
String pwd = p.getProperty("pwd");
System.out.println(user);
System.out.println(pwd);
}
五、ClassLoader
类加载器是用来把类(class)装载进内存的。JVM 规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定义加载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:
引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来加载核心类库。该加载器无法直接获取
扩展类加载器:负责jre/lib/ext目录下的jar包或 –D java.ext.dirs 指定目录下的jar包装入工作库
系统类加载器:负责java –classpath 或 –D java.class.path所指的目录下的类与jar包装入工作 ,是最常用的加载器
//1.获取一个系统类加载器
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);
//2.获取系统类加载器的父类加载器,即扩展类加载器
classloader = classloader.getParent();
System.out.println(classloader);
//3.获取扩展类加载器的父类加载器,即引导类加载器
classloader = classloader.getParent();
System.out.println(classloader);
//4.测试当前类由哪个类加载器进行加载
classloader =
Class.forName("exer2.ClassloaderDemo").getClassLoader();
System.out.println(classloader);
//5.测试JDK提供的Object类由哪个类加载器加载
classloader =
Class.forName("java.lang.Object").getClassLoader();
System.out.println(classloader);
//*6.关于类加载器的一个主要方法:getResourceAsStream(String str):获取类路径下的指定文件的输入流
InputStream in = null;
in = this.getClass().getClassLoader().getResourceAsStream("exer2\\test.properties");
System.out.println(in);
六、创建类对象
创建类的对象,调用Class对象的newInstance()方法 要 求: 1)类必须有一个无参数的构造器。 2)类的构造器的访问权限需要足够。难道没有无参的构造器就不能创建对象了吗? 不是!只要在操作的时候明确的调用类中的构造方法,并将参数传递进去之后,才可以实例化操作。步骤如下: 1)通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器 2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。 3)通过Constructor实例化对象。
//1.根据全类名获取对应的Class对象
String name = “atguigu.java.Person";
Class clazz = null;
clazz = Class.forName(name);
//2.调用指定参数结构的构造器,生成Constructor的实例
Constructor con = clazz.getConstructor(String.class,Integer.class);
//3.通过Constructor的实例创建对应类的对象,并初始化类属性
Person p2 = (Person) con.newInstance("Peter",20);
System.out.println(p2);
public class CushContext {
private static final String[] CUSH_CLASS_NAME = {
"main.java.celue.celue5.CushNormal",
"main.java.celue.celue5.CushRebate",
"main.java.celue.celue5.CushReturn"
};
CushSuper cushSuper=null;
public CushContext(String type,Class[] paramsType, Object[] parmas) {
int type2=Integer.parseInt(type);
try {
Class<?> clazz=Class.forName(CUSH_CLASS_NAME[type2]);
Constructor<?> constructor=clazz.getConstructor(paramsType);
this.cushSuper=(CushSuper)constructor.newInstance(parmas);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public double getResult(double money){
return cushSuper.attachMoney(money);
}
}
七、通过反射调用类的完整结构
Field、Method、Constructor、Superclass、Interface、Annotation
Field
package com.atguigu.testReflect;
import com.atguigu.reflect.Person;
import org.junit.Test;
import java.io.FileDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
*测试属性
*/
public class TestFileld {
/**
* 获取运行时类的属性
*/
@Test
public void test() {
Class<Person> cla = Person.class;
//只能获取(运行时类及父类到属性)修饰符为public的属性
Field[] fields = cla.getFields();
for(Field field:fields){
System.out.println(field);
}
/**
* getDeclaredFields :只能获取运行时类本身定义的属性,包括私有属性
*/
Field[] f2 = cla.getDeclaredFields();
for(Field f : f2){
System.out.println(f);
}
}
/**
* 属性的:权限修饰符,变量类型,变量名称,变量值
* 获取属性的各个部分
*/
@Test
public void test2() {
Class<Person> cla = Person.class;
Field[] fields = cla.getDeclaredFields();
for(Field f : fields){
//权限修饰符
int i = f.getModifiers();
String s = Modifier.toString(i);
System.out.print(s + " ");
//变量类型
Class<?> type = f.getType();
System.out.print(type.getName()+" ");
//变量名称
String name = f.getName();
System.out.println(name);
System.out.println();
}
}
/**
* 获取指定类的属性
*/
@Test
public void test3() throws Exception {
Class<Person> cls = Person.class;
//获取指定的属性getField 只能获取运行时和父类中public的属性
Field name = cls.getField("name");
//创建运行时对象
Person person = cls.newInstance();
name.set(person,"王法");
System.out.println(person);
//获取属性的值
Object o = name.get(person);
System.out.println(o);
//可以获取运行时类的声明的属性,包括私有的
Field age = cls.getDeclaredField("age");
//由于属性修饰符的限制,可以设置setAccessible为true,就可以操作私有属性
age.setAccessible(true);
age.set(person,10);
System.out.println(person);
Field id = cls.getDeclaredField("id");
id.setAccessible(true);
id.set(person,111);
System.out.println(person);//Person{name='王法', age=10, id=111}
//调用静态方法
、// 获取运行类中和父类中public的声明的方法
Method info = cls.getMethod("info");
// info.invoke(null);
info.invoke(Person.class);
//获取运行时中声明的方法
Method method = cls.getDeclaredMethod("fly", String.class);
method.setAccessible(true);
Object china = method.invoke(person, "China");
System.out.println(china);//1
}
}
Method
package com.atguigu.testReflect;
import com.atguigu.reflect.Person;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.sql.Types;
/**
* Created by admin on 2019/5/10 17:26
*
* @Author: created by admin
* @Date: created in 17:26 2019/5/10
* @param: bindingResult
* @param: result
* @return:
* @throws:
* @Description:
* @version:
*/
public class TestMethod {
@Test
public void test() {
Class<Person> cla = Person.class;
//获取运行时类中和父类中声明为public的方法
Method[] methods = cla.getMethods();
for(Method m:methods){
System.out.println(m);
}
System.out.println();
//获取运行时类本身声明的方法
Method[] methods1 = cla.getDeclaredMethods();
for(Method t : methods1){
System.out.println(t);
}
}
//注解,修饰符,返回值类型,方法名,形参列表,异常等
@Test
public void test2() {
Class<Person> cla = Person.class;
Method[] methods1 = cla.getDeclaredMethods();
for(Method t : methods1){
//注解
Annotation[] as = t.getAnnotations();
for(Annotation a :as){
System.out.println(a);
}
//修饰符
int modifiers = t.getModifiers();
System.out.print(Modifier.toString(modifiers) +" ");
//返回值类型
Class<?> type = t.getReturnType();
System.out.print(type+" ");
//方法名
System.out.print(t.getName()+" ");
//形参列表
System.out.print("(");
Class<?>[] types = t.getParameterTypes();
for(Class c : types){
System.out.print(c.getName() +" ");
}
Parameter[] parameters = t.getParameters();
for(Parameter p : parameters){
System.out.print(p.getName()+" ");
}
System.out.print(")");
//异常
Class<?>[] types1 = t.getExceptionTypes();
if(types1.length>0){
System.out.print("throws " );
}
for(Class c: types1){
System.out.print(c.getName());
}
//
Type[] types2 = t.getGenericExceptionTypes();
for(Type c: types2){
System.out.println(c.getTypeName());
}
System.out.println();
}
}
/**
* 获取运行时类的指定方法
*/
@Test
public void test3() throws Exception {
Class<Person> cls = Person.class;
//获取运行类中和父类中public的声明的方法
Method show = cls.getMethod("show");
System.out.println(show.getName());
Person p = cls.newInstance();
//调用方法
Object invoke = show.invoke(p);
System.out.println(invoke);
Method toString = cls.getMethod("toString");
Object invoke1 = toString.invoke(p);
System.out.println(invoke1);
}
}
Constructor
package com.atguigu.testReflect;
import com.atguigu.reflect.Person;
import org.junit.Test;
import java.lang.reflect.Constructor;
/**
* Created by admin on 2019/5/13 21:25
*
* @Author: created by admin
* @Date: created in 21:25 2019/5/13
* @param: bindingResult
* @param: result
* @return:
* @throws:
* @Description:
* @version:
*/
public class TestConstructor {
@Test
public void test() throws Exception {
Class<?> cls = Class.forName("com.atguigu.reflect.Person");
//创建对应的运行时对象,使用newInstance方法实际上调用的运行时类的空参构造器
//要想能能创建成功,必须有空参构造器,并且权限要能足够
Object o = cls.newInstance();
Person p = (Person)o;
System.out.println(p);
}
@Test
public void test1() throws Exception {
//获取声明的所有的构造器
Class<?> cls = Class.forName("com.atguigu.reflect.Person");
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for(Constructor c:constructors){
System.out.println(c);
}
}
/**
* 获取指定的构造器
* @throws Exception
*/
@Test
public void test2() throws Exception {
Class<?> cls = Class.forName("com.atguigu.reflect.Person");
Constructor constructor = cls.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
Person person = (Person) constructor.newInstance("王五", 23);
System.out.println(person);
}
}
uperclass、Interface、Annotation其他等
package com.atguigu.testReflect;
import com.atguigu.reflect.Person;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Created by admin on 2019/5/13 21:41
*
* @Author: created by admin
* @Date: created in 21:41 2019/5/13
* @param: bindingResult
* @param: result
* @return:
* @throws:
* @Description:
* @version:
*/
public class TestOther {
//获取运行时的父类
@Test
public void test() {
Class<Person> cls = Person.class;
Class<? super Person> aClass = cls.getSuperclass();
System.out.println(aClass);
}
//获取带泛型的父类getGenericSuperclass
@Test
public void test2() {
Class<Person> cls = Person.class;
Type type = cls.getGenericSuperclass();
System.out.println(type);
}
//获取父类的泛型
@Test
public void test3() {
Class<Person> cls = Person.class;
Type type = cls.getGenericSuperclass();
ParameterizedType t = (ParameterizedType)type;
Type[] arguments = t.getActualTypeArguments();
System.out.println(arguments.getClass());
String typeName = arguments[0].getTypeName();
//得到弗雷德泛型
System.out.println(typeName);
for(Type m:arguments) {
System.out.println(m);
}
}
/**
* 获取实现的接口
*/
@Test
public void test4() {
Class<Person> cls = Person.class;
Class<?>[] interfaces = cls.getInterfaces();
for(Class c: interfaces) {
System.out.println(c);
}
}
/**
* 获取所在包
*/
@Test
public void test5() {
Class<Person> cls = Person.class;
Package aPackage = cls.getPackage();
System.out.println(aPackage);
}
/**
* 获取类注解
*/
@Test
public void test6() {
Class<Person> cls = Person.class;
Annotation[] annotations = cls.getAnnotations();
for(Annotation a : annotations) {
System.out.println(a );
}
}
}
八 、PropertyDescriptor类:(属性描述器)、Introspector类
内省(Introspector) 是Java 语言对JavaBean类属性、事件的一种缺省处理方法。
JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。
@Data
public class UserInfo {
private long userId;
private String userName;
private int age;
private String emailAddress;
}
1、JDK内省类库:
PropertyDescriptor类:(属性描述器)
PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
1. getPropertyType(),获得属性的Class对象;
2. getReadMethod(),获得用于读取属性值的方法;
3. getWriteMethod(),获得用于写入属性值的方法;
4. hashCode(),获取对象的哈希值;
5. setReadMethod(Method readMethod),设置用于读取属性值的方法;
6. setWriteMethod(Method writeMethod),设置用于写入属性值的方法。
package com.peidasoft.instrospector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class BeanInfoUtil {
// 设置bean的某个属性值
public static void setProperty(UserInfo userInfo, String userName) throws Exception {
// 获取bean的某个属性的描述符
PropertyDescriptor propDesc = new PropertyDescriptor(userName, UserInfo.class);
// 获得用于写入属性值的方法
Method methodSetUserName = propDesc.getWriteMethod();
// 写入属性值
methodSetUserName.invoke(userInfo, "wong");
System.out.println("set userName:" + userInfo.getUserName());
}
// 获取bean的某个属性值
public static void getProperty(UserInfo userInfo, String userName) throws Exception {
// 获取Bean的某个属性的描述符
PropertyDescriptor proDescriptor = new PropertyDescriptor(userName, UserInfo.class);
// 获得用于读取属性值的方法
Method methodGetUserName = proDescriptor.getReadMethod();
// 读取属性值
Object objUserName = methodGetUserName.invoke(userInfo);
System.out.println("get userName:" + objUserName.toString());
}
}
2、Introspector类:
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。具体代码如下:
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class BeanInfoUtil {
// 通过内省设置bean的某个属性值
public static void setPropertyByIntrospector(UserInfo userInfo, String userName) throws Exception {
// 获取bean信息
BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);
// 获取bean的所有属性列表
PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();
// 遍历属性列表,查找指定的属性
if (proDescrtptors != null && proDescrtptors.length > 0) {
for (PropertyDescriptor propDesc : proDescrtptors) {
// 找到则写入属性值
if (propDesc.getName().equals(userName)) {
Method methodSetUserName = propDesc.getWriteMethod();
methodSetUserName.invoke(userInfo, "alan"); // 写入属性值
System.out.println("set userName:" + userInfo.getUserName());
break;
}
}
}
}
// 通过内省获取bean的某个属性值
public static void getPropertyByIntrospector(UserInfo userInfo, String userName) throws Exception {
BeanInfo beanInfo = Introspector.getBeanInfo(UserInfo.class);
PropertyDescriptor[] proDescrtptors = beanInfo.getPropertyDescriptors();
if (proDescrtptors != null && proDescrtptors.length > 0) {
for (PropertyDescriptor propDesc : proDescrtptors) {
if (propDesc.getName().equals(userName)) {
Method methodGetUserName = propDesc.getReadMethod();
Object objUserName = methodGetUserName.invoke(userInfo);
System.out.println("get userName:" + objUserName.toString());
break;
}
}
}
}
}
3、BeanUtils工具包:
由上述可看出,内省操作非常的繁琐,所以所以Apache开发了一套简单、易用的API来操作Bean的属性——BeanUtils工具包。
BeanUtils工具包:下载:BeanUtils – Commons,注意:应用的时候还需要一个logging包Apache Commons Logging - Overview
使用BeanUtils工具包完成上面的测试代码:
package com.peidasoft.instrospector;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class BeanInfoTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
UserInfo userInfo = new UserInfo();
userInfo.setUserName("peida");
try {
BeanUtils.setProperty(userInfo, "userName", "peida");
System.out.println("set userName:" + userInfo.getUserName());
System.out.println("get userName:" + BeanUtils.getProperty(userInfo, "userName"));
BeanUtils.setProperty(userInfo, "age", 18);
System.out.println("set age:" + userInfo.getAge());
System.out.println("get age:" + BeanUtils.getProperty(userInfo, "age"));
System.out.println("get userName type:" + BeanUtils.getProperty(userInfo, "userName").getClass().getName());
System.out.println("get age type:" + BeanUtils.getProperty(userInfo, "age").getClass().getName());
PropertyUtils.setProperty(userInfo, "age", 8);
System.out.println(PropertyUtils.getProperty(userInfo, "age"));
System.out.println(PropertyUtils.getProperty(userInfo, "age").getClass().getName());
PropertyUtils.setProperty(userInfo, "age", "8"); // IllegalArgumentException
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果:
[java] view plain copy
set userName:peida
get userName:peida
set age:18
get age:18
get userName type:java.lang.String
get age type:java.lang.Stringjava.lang.Integer
Exception in thread "main" java.lang.IllegalArgumentException: Cannot invoke com.peidasoft.instrospector.UserInfo.setAge on bean class
'class com.peidasoft.instrospector.UserInfo' - argument type mismatch - had objects of type "java.lang.String" but expected signature "int"
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2181)
at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2097)
at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1903)
at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:2010)
at org.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:896)
at com.peidasoft.instrospector.BeanInfoTest.main(BeanInfoTest.java:32)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2116)
... 5 more
说明:
1. 获得属性的值,例如,BeanUtils.getProperty(userInfo, “userName”),返回字符串。
2. 设置属性的值,例如,BeanUtils.setProperty(userInfo, “age”, 8),参数是字符串或基本类型自动包装。设置属性的值是字符串,获得的值也是字符串,不是基本类型。
3. BeanUtils的特点:
1). 对基本数据类型的属性的操作:在WEB开发、使用中,录入和显示时,值会被转换成字符串,但底层运算用的是基本类型,这些类型转到动作由BeanUtils自动完成。
2). 对引用数据类型的属性的操作:首先在类中必须有对象,不能是null,例如,private Date birthday=new Date();。操作的是对象的属性而不是整个对象,例如,BeanUtils.setProperty(userInfo, “birthday.time”, 111111);
package com.peidasoft.Introspector;
import java.util.Date;
public class UserInfo {
private Date birthday = new Date(); // 引用类型的属性,不能为null
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getBirthday() {
return birthday;
}
}
package com.peidasoft.Beanutil;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import com.peidasoft.Introspector.UserInfo;
public class BeanUtilTest {
public static void main(String[] args) {
UserInfo userInfo=new UserInfo();
try {
BeanUtils.setProperty(userInfo, "birthday.time","111111"); // 操作对象的属性,而不是整个对象
Object obj = BeanUtils.getProperty(userInfo, "birthday.time");
System.out.println(obj);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
PropertyUtils类和BeanUtils不同在于,运行getProperty、setProperty操作时,没有类型转换,使用属性的原有类型或者包装类。由于age属性的数据类型是int,所以方法PropertyUtils.setProperty(userInfo,”age”, “8”)会爆出数据类型不匹配,无法将值赋给属性。