------- android培训、java培训、期待与您交流! ----------
>>JAVA1.2时就存在反射,并不是1.5的新特性
>>类Class(平时定义时是小写的class,这个是一个类,名字叫Class)
Class代表一类什么样的事物?
Java类用于描述一类事物的共性,该类该有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同实例对象有不同的属性值。Java程序中的各个java类,它们是否属于同一类事物,是不是可以用一个类来描述?这个类的名字就是Class。
Class描述了类的名字、类的访问属性、类所属于的包名、字段名的列表、方法名称的列表、等等。
理解:比如Person代表人,具体的实例对象就是如“小强”、“志明”这样的人。所以,Class代表类,具体的实例就是各个类在内存中的字节码。
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示。
Eg:理解
//两个人
Person p1 = new Person();
Person p2 = new Person();
//Class
Class class1 = new Class(); //编译报错,不可以new的
Class cla1 = 字节码1;
Class cla2 = 字节码2;
Class class1 = Date.class;
Class class2 = Math.class;
如何得到各个字节码对应的实例对象(Class类型)
1) 类名.class,例如System.class
2) 对象.getClass(),例如newDate().getClass()
3) Class.forName(“类名”),例如Class.forName(“java.util.Date”);
基本数据类型也有对应的Class的,称为9个预定义类型:(来自API)
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Eg:void也是预定义Class实例对象
……………………
Class cla = void.class; //允许
……………………
Eg:内存中的字节码,它们相等吗?
package cn.com.cty;
import java.util.Date;
public class ClassTest {
//为演示方便不处理异常
publicstatic void main(String[] args) throws ClassNotFoundException {
Stringstr = "durex";
Classcla1 = str.getClass();
Classcla2 = String.class;
Classcla3 = Class.forName("java.lang.String");
System.out.println(cla1== cla2); //true
System.out.println(cla2== cla3); //true
Stringstr2 = "jissbon";
Classcla4 = str2.getClass();
//是预定义类型吗?
System.out.println(cla4.isPrimitive()); //false
System.out.println(int.class.isPrimitive()); //true
//相等吗(Integer是int的一个包装类)
System.out.println(int.class== Integer.class); //false
//Integer中提供了一个TYPE常量来代表包装类型包装的那个基本类型的字节码
System.out.println(int.class== Integer.TYPE); //true
/*其它包装类型中也提供了TYPE(来自API对isPrimitive的解释)
Boolean.TYPE,Character.TYPE, Byte.TYPE, Short.TYPE,
Integer.TYPE,Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE*/
//基本类型的数组呢?
System.out.println(int[].class.isPrimitive()); //false
System.out.println(int[].class.isArray()); //true
}
}
>>反射
反射就是把Java类中的各种成分映射成相应的java类。--某人总结
例如,一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量、方法、构造方法、包等等信息也用一个个java类来表示,就像汽车是一个类,汽车中的发动机、变速箱等等也是一个个类。表示java类的Class类显然要提供一系列方法来获取其中的变量、构造方法、方法等等的信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
反射会导致程序性能下降。
>>构造方法的反射应用
java.lang.reflect
类 Constructor
java.lang.Object
java.lang.reflect.AccessibleObject
java.lang.reflect.Constructor
类型参数:T - 在其中声明构造方法的类。
Eg:入门例子
……………………
//所有的
Constructor[] constructor = Class.forName(“java.lang.String”).getConstructor();
//指定的,我要有参还是无参的?
Constructor constructor1
= Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
//用反射实现new String(newStringBuffer(“durex”));
String str
= (String)constructor1.newInstance(newStringBuffer(“durex”));
sop(str.charAt(2)); //输出第三个字符验证
……………………
注意:以上例子中
String str
= (String)constructor1.newinstance(newStringBuffer(“durex”));
如果写成
String str
= (String)constructor1.newinstance(“abc”);
则编译时正常,运行时报错。因为反射的不是带String参数的构造函数,特别注意。
以上例子中,其实可以省略从Class->constructor->new的过程,Class中有newInstence()方法。
>>成员变量反射应用
java.lang.reflect
类 Field
java.lang.Object
java.lang.reflect.AccessibleObject
java.lang.reflect.Field
Field代表某个类中的一个成员变量。那么,得到的Field对象是对应到类上的成员变量,还是对应到该类创建的对象上的成员变量呢?
Eg:说明例子,包括反射和暴力反射
package cn.com.cty;
import java.lang.reflect.Field;
import java.util.Date;
public class ReflectFieldDemo {
/**
* @param args
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
publicstatic void main(String[] args) throws SecurityException, NoSuchFieldException,IllegalArgumentException, IllegalAccessException {
/*Person类
publicString name; //注意这个是公有的
privateint age;
privateString address;
privateDate birthday;*/
Personp = new Person("durex", 20, "what", new Date());
//反射成员变量,这里只能反射public定义的变量
Fieldf1 = p.getClass().getField("name");
//现在,f1上的值是durex吗?错!现在f1只代表一个变量,是类上的变量
//现在想取出这个变量在某个对象上的值
Stringname = (String) f1.get(p);
System.out.println(name);
//想取出private定义的变量怎么办?
//使用getField报NoSuchFieldException
Fieldf2 = p.getClass().getDeclaredField("age");
f2.setAccessible(true);//暴力反射
intage = f2.getInt(p);
System.out.println(age);
/*如果没有设定暴力反射,则虽然可以找到变量(不会报NoSuchFieldException),
但不能使用(报IllegalArgumentException,IllegalAccessException)
这里张老师有一个形象的比喻:好比一个鸟人,拿钱在你面前晃(可以找到变量),
但是不让你用他的钱(不合法的access),我们一气之下暴力抢夺(暴力反射)。
*/
}
}
>>综合应用:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“b”换成“a”。
Eg:self
package cn.com.cty;
import java.lang.reflect.Field;
import java.util.Date;
public class ReflectFieldApp {
publicstatic void main(String[] args) {
Personp = new Person();
Personnewp = new Person();
p.setName("bbbbx");
p.setAge(20);
p.setAddress("bbboooxxxbbb");
p.setBirthday(newDate());
newp= (Person) replace(p);
System.out.println(p.getName()+
"|||"+ p.getAge() +
"|||"+ p.getAddress() +
"|||"+ p.getBirthday());
}
publicstatic Object replace(Object obj)
{
Field[]fields = obj.getClass().getDeclaredFields();
for(Fieldfield : fields)
{
//暴力反射
field.setAccessible(true);
//因为每个类字节码在内存只有一份,所以用等号比equals好
if((field.getType())== (String.class))
{
try{
StringoldValue = (String)field.get(obj);
StringnewValue = oldValue.replace('b', 'a');
field.set(obj,newValue);
}catch (IllegalArgumentException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}catch (IllegalAccessException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
returnobj;
}
}
输出:aaaax|||20|||aaaoooxxxaaa|||Tue Apr 02 11:09:37 CST 2013
和老师打的差不多,就这么着吧。
>>成员方法反射应用
java.lang.reflect
类 Method
java.lang.Object
java.lang.reflect.AccessibleObject
java.lang.reflect.Method
getMethod
public Method getMethod(String name, Class>... parameterTypes)
throws NoSuchMethodException,SecurityException
Eg:入门例子
//获取
Method rCharAt
= Class.forName(“java.lang.String”).getMethod(“chatAt”,int.class);
//调用
//通常方式
sop(str.charAt);
//反射方式
sop(rCharAt.invoke(str,2));
说明:invoke是调用方法对象上的方法。可以这么理解,列车司机停住了列车,其实是列车自己刹住的,司机只是发了命令。
如果传递给invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法,调用其不需要对象。
当然,1.4和1.5的区别在于是否有可变参数:
public Object invoke(Object obj, Object...args)
throwsIllegalAccessException, IllegalArgumentException, InvocationTargetException
如果使用1.4的方式调用也是可以的:
System.out.println(rCharAt.invoke( str, newObject[]{ 2 } ) );
>>调用任意类的main方法
eg:一般调用main方法
/*试验用的带main方法的类*/
package cn.com.cty;
public class TempTest {
/**
* @param args
*/
publicstatic void main(String[] args) {
//输出传入的参数
for(Stringstr : args)
{
System.out.println(str);
}
}
}
/*调用TempTest类的main方法*/
package cn.com.cty;
public class ReflectMethodDemo {
publicstatic void main(String[] args) {
TempTest.main(newString[]{"durex","jissbon","what"});
}
}
输出:
durex
jissbon
what
eg:反射方式调用
package cn.com.cty;
import java.lang.reflect.Method;
public class ReflectMethodDemo {
publicstatic void main(String[] args) throws Exception{
//TempTest.main(newString[]{"durex","jissbon","what"});
//演示方便,简单处理异常
MethodmainMethod =
Class.forName("cn.com.cty.TempTest").getMethod("main",String[].class);
/*
mainMethod.invoke(null,new String[]{"durex","jissbon","what"});
//运行时异常,java.lang.IllegalArgumentException:wrong number of arguments
//因为为了兼容1.4,这样传入的参数会被拆开,等于传入了3个参数,而main只
接收一个数组参数
*/
//解决方法1
//再打一个包来解决这个问题,将数组放到数组中去,拆开后还是一个数组
Object[]obj = {new String[]{"durex","jissbon","what"}};
mainMethod.invoke(null,obj);
//解决方法2
//将String数组当成Object,具体原因待考究
mainMethod.invoke(null,(Object)new String[]{"durex","jissbon","what"});
}
}
>>数组的反射
API中解释:每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。即具有相同元素类型和相同维度的数组都属于同一个Class对象。
eg:一系列试验
package cn.com.cty;
import java.util.Arrays;
public class ReflectArrayDemo {
publicstatic void main(String[] args) {
int[]a1 = new int[3];
int[]a2 = new int[3];
int[]a3 = new int[5];//不同个数
int[][]a4 = new int[5][5];//不同维度
String[]a5 = new String[3];//不同类型
System.out.println(a1== a2); //false
System.out.println(a1.getClass()== a2.getClass()); //true
System.out.println(a1.getClass()== a3.getClass()); //true
System.out.println(a1.getClass()== a4.getClass()); //false
//System.out.println(a1== a5); //编译即报错
System.out.println(a1.getClass()== a5.getClass()); //false
//查看名字
System.out.println(a1.getClass().getName());//输出[I,什么意思呢?
/*查看API的getName()方法解释
如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 '[' 字符加元素类型名。元素类型名的编码如下:
ElementType Encoding
boolean Z
byte B
char C
classor interface Lclassname;
double D
float F
int I
long J
short S */
//查看父类,输出java.lang.Object
System.out.println(a1.getClass().getSuperclass().getName());
//父类都是Object,做个试验,都改成Object
Objectobj1 = a1;
Objectobj2 = a4;//a4是二维数组
Objectobj3 = a5;//a5是String类型
Object[]obj4 = a5;
//Object[]obj5 = a1;//a1是int型,基本数据类型,不能放入Object数组
Object[] obj6 = a4;//a4是二维数组
//由上面的试验引申出的一些问题
//重新定义一些数组来做试验,注意格式,赋值了就不用规定大小了
//int[]arr1 = new int[3]{1,2,3};
int[]arr1 = new int[]{1,2,3};
String[]arr2 = new String[]{"durex","jissbon","what"};
int[][]arr3 = new int[][]{{11,22,33},{44,55,66}};
String[][]arr4 = newString[][]{{"11","22","33"},{"44","55","66"}};
//用工具类输出
System.out.println(Arrays.asList(arr1));
System.out.println(Arrays.asList(arr2));
System.out.println(Arrays.asList(arr3));
System.out.println(Arrays.asList(arr4));
/*输出:
[[I@c17164]
[durex,jissbon, what]//只有字符串类型的输出了
[[I@1fb8ee3,[I@61de33]
[[Ljava.lang.String;@14318bb,[Ljava.lang.String;@ca0b6]
为什么呢?
在1.5中,asList()是这样定义的
publicstatic
在1.4中,asList()是这样定义的
publicstatic List asList(Object[] obj)
结合上面的Object试验,String是在1.4处理的,等效于多个参数,而int在1.5处
理,当做一个参数
*/
}
}
eg:打印数组或任意对象
package cn.com.cty;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ReflectArrayDemo {
publicstatic void main(String[] args) {
int[]arr1 = new int[]{1,2,3};
Objectobj = arr1;
printObject(obj);
printObject("durex");
}
private static void printObject(Object obj){
Classclazz = obj.getClass();
//判断是不是数组
if(clazz.isArray())
{
intlen = Array.getLength(obj);
for(intx=0 ; x { System.out.println(Array.get(obj,x)); } } else { System.out.println(obj); } } >>hashCode分析,面试题目,hashCode的功能 一个集合是否包含某个对象,怎么查找呢?通常逐一取出每个元素和要查找的对象对比,当某个元素和要查找的对象的equal是方法比较结果相同时,返回肯定信息。但是如果当集合中有非常多的元素且不包含要查找的信息,显然,很没有效率。 于是有人发明了一种哈希算法来提高效率,这种方法将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储在那个区域。 HashSet集合就是采用哈希算法存取对象的集合,它内部采用对某个数字n进行取余的方式对哈希码进行分组和划分存储区域。 Object类中定义了一个hashCode方法来返回每个java对象的哈希码。当从HashSet集合中查找对象时,java系统首先调用对象的hashCode方法获取该对象的哈希码,然后根据哈希码找到相应的存储区域,最后取出该区域内的每个元素与该对象进行equals方法比较。 eg:说明例子 …………………… //复写了Person类中的hashCode()和equals()方法 publicint hashCode() { finalint prime = 47; intresult = 1; result= prime * result + age; result= prime * result + ((name == null) ? 0 : name.hashCode()); returnresult; } publicboolean equals(Object obj) { if(this == obj) returntrue; if(obj == null) returnfalse; if(getClass() != obj.getClass()) returnfalse; final Person other = (Person) obj; if(age != other.age) returnfalse; if(name == null) { if(other.name != null) returnfalse; }else if (!name.equals(other.name)) returnfalse; returntrue; } …………………… package cn.com.cty; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; public class ReflectHashCodeAnalyse { publicstatic void main(String[] args) { //Collectioncoll = new ArrayList(); Collectioncoll = new HashSet();//不能重复 //Person中,名字和年龄相同认为是“一个人” Personp1 = new Person("durex",20,"1",new Date()); Personp2 = new Person("jissbon",18,"2",new Date()); Personp3 = new Person("what",25,"3",new Date()); Personp4 = new Person("durex",20,"4",new Date());//和p1同 coll.add(p1); coll.add(p2); coll.add(p3); coll.add(p4);//试验1 coll.add(p1);//试验2 //复写equals方法 System.out.println(p1.equals(p4)); //true //没有复写hashCode前为4(试验2排除),之后为3(实验1排除) System.out.println(coll.size()); } } 说明:没有复写hashCode前size为4。因为虽然p4和p1的equals结果为true。但是p1和p4被存放到了不同的区域,所以p4可以被add进HashSet集合。 所以有说法,equals相等的,应让其hashCode也相等。所以复写了hashCode方法后,size为3。 但是反过来可以不成立,即hashCode相同的两个对象equals可以不等。 当一个对象呗存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希码的属性了,否则,对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去Hashset集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除该对象,造成“内存泄露”。 eg:修改导致内存泄露 //在上一个例子的基础上,修改已经加入HashSet集合的对象属性值 package cn.com.cty; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; public class ReflectHashCodeAnalyse { publicstatic void main(String[] args) { //Collectioncoll = new ArrayList(); Collectioncoll = new HashSet();//不能重复 //Person中,名字和年龄相同认为是“一个人” Personp1 = new Person("durex",20,"1",new Date()); Personp2 = new Person("jissbon",18,"2",new Date()); Personp3 = new Person("what",25,"3",new Date()); Personp4 = new Person("durex",20,"4",new Date());//和p1同 coll.add(p1); coll.add(p2); coll.add(p3); coll.add(p4);//试验1 coll.add(p1);//试验2 System.out.println("修改之前size:"+coll.size());//3 p1.setAge(40); coll.remove(p1); //内部调用了equals System.out.println("修改之后size:"+coll.size());//3,没删除 } } >>反射实现框架功能 框架与工具类的区别:工具类是被用户的类调用,而框架则是调用用户提供的类。 好比我提供房子(框架),用户自己安装门窗,把门窗插入我提供的房子(框架)。 因为在写程序时无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象,而要用反射来创建。 eg:使用反射和配置文件来模拟框架,配置文件暂时放在根目录下 //————————配置文件config.properties———————— className=java.util.ArrayList //————————main———————— package cn.com.cty; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Date; import java.util.Properties; public class ReflectFromProp { publicstatic void main(String[] args) throws Exception { BufferedInputStreambis = newBufferedInputStream( newFileInputStream("config.properties")); Propertiesprop = new Properties(); prop.load(bis); StringclassName = prop.getProperty("className"); Collectioncoll = (Collection)Class.forName(className).newInstance(); Personp1 = new Person("durex",20,"1",new Date()); Personp2 = new Person("jissbon",18,"2",new Date()); Personp3 = new Person("what",25,"3",new Date()); coll.add(p1); coll.add(p2); coll.add(p3); System.out.println(coll.size()); } } >>类加载器 上一个例子的配置文件放在根目录下,那么配置文件放在其他地方怎么办?上一个例子用的是相对路径且是相对于当前工作目录。 eg:改变config.properties的位置,同时使用类加载器改造上一个例子 package cn.com.cty; import java.io.InputStream; import java.util.Collection; import java.util.Date; import java.util.Properties; public class ReflectFromProp { publicstatic void main(String[] args) throws Exception { /* * BufferedInputStream bis = newBufferedInputStream( new *FileInputStream("config.properties")); */ //使用类加载器 /*InputStreambis = (InputStream) ReflectFromProp.class .getClassLoader().getResourceAsStream( "cn/com/cty/config.properties");*/ //偷懒方式 InputStreambis = ReflectFromProp.class.getResourceAsStream("config.properties"); Propertiesprop = new Properties(); prop.load(bis); StringclassName = prop.getProperty("className"); Collectioncoll = (Collection) Class.forName(className).newInstance(); Personp1 = new Person("durex", 20, "1", new Date()); Personp2 = new Person("jissbon", 18, "2", new Date()); Personp3 = new Person("what", 25, "3", new Date()); coll.add(p1); coll.add(p2); coll.add(p3); System.out.println(coll.size()); } } 说明:但是这种方法只能读,还不能向config.properties中写入。 >>内省(introspector),且引出JavaBean JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。 如果要在两个模块之间传递信息,那么可以将信息封装到JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,VO)。这些信息在类中使用私有字段来存储,而读取和设置则通过set和get方法来进行。 JavaBean有什么属性是根据set和get方法的方法名来决定的。 eg:属性名字,命名规则 //方法名去掉set或get后作为属性名 //如果第二个字母是小的,则把第一个字母变成小的 setAge()àage setage()àage //如果第二个字母是大的,则保持不变 getCPUàCPU eg:对JavaBean的内省,使用属性描述符 package cn.com.cty; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; importjava.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class IntrospectorBeanDemo { publicstatic void main(String[] args) throws Exception { //Person为JavaBean,有name属性 Personp = new Person(); Stringname = ""; //set属性name的值 propertiesSet(p,"name", "durex"); //get属性name的值 name= (String) propertiesGet(p, "name"); System.out.println(name); } /** * 内省set方法 * @param bean * @param propertyName * @param setValue * @throws Exception */ privatestatic void propertiesSet(Object bean, String propertyName, ObjectsetValue) throws Exception { //调用属性描述符类 PropertyDescriptorpd = new PropertyDescriptor(propertyName, bean .getClass()); //得到set方法 MethodsetMethod = pd.getWriteMethod(); //调用set方法 setMethod.invoke(bean,setValue); } /** * 内省get方法 * @param bean * @param propertyName * @return * @throws Exception */ privatestatic Object propertiesGet(Object bean, String propertyName) throwsException { //调用属性描述符类 PropertyDescriptorpd = new PropertyDescriptor(propertyName, bean .getClass()); //得到get方法 MethodgetMethod = pd.getReadMethod(); //调用get方法 ObjectretValue = getMethod.invoke(bean, null); returnretValue; } } >>对Bean更多的内省操作 采用遍历BeanInoffensive的所有属性方式来查找和设置某个对象的某个属性。在程序中把一个类当做JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到BeanInfo对象封装了把这个类当做JavaBean看的结果信息。 eg:为说明而采用一种复杂的方式内省get方法 private static Object propertiesGet(Objectbean, String propertyName) throwsException { /* //调用属性描述符类 PropertyDescriptorpd = new PropertyDescriptor(propertyName, bean .getClass()); //得到get方法 MethodgetMethod = pd.getReadMethod(); //调用get方法 Object retValue =getMethod.invoke(bean, null); returnretValue; */ //使用BeanInfo来获取get方法 BeanInfobeanInfo = Introspector.getBeanInfo(bean.getClass()); PropertyDescriptor[]props = beanInfo.getPropertyDescriptors(); ObjectretValue = null; for(PropertyDescriptorprop : props) { if(prop.getName().equals(propertyName)) { //得到get方法 MethodgetMethod = prop.getReadMethod(); //调用get方法 retValue= getMethod.invoke(bean, null); break; } } returnretValue; } 比上一个例子麻烦,这里只是器说明作用。 >>BeanUtils工具包 commons-beanutils.jar commons-logging.jar eg:入门演示 package cn.com.cty; import java.util.Date; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.Map.Entry; importorg.apache.commons.beanutils.BeanUtils; public class BeanUtilsDemo { publicstatic void main(String[] args) throws Exception{ Personp = new Person(); p.setName("durex"); p.setAge(20); p.setAddress("what"); p.setBirthday(newDate()); //报错,.NoClassDefFoundError:org/apache/commons/logging/LogFactory //没有引入logging包 System.out.println(BeanUtils.getProperty(p,"name")); //设置 BeanUtils.setProperty(p,"age",30); System.out.println(p.getAge()); //Date类中有方法setTime,所以time是一个属性 //setProperty支持级联操作 BeanUtils.setProperty(p,"birthday.time", 99999); System.out.println(BeanUtils.getProperty(p,"birthday")); //这里是上面已经初始化”p.setBirthday(newDate());“,否则因为级联操作找不到实例而报异常 //java.lang.IllegalArgumentException:No bean specified /*以上输出: durex 30 ThuJan 01 08:01:39 CST 1970*/ //拷贝所有属性到另一个bean中 Personp2 = new Person(); BeanUtils.copyProperties(p2,p); System.out.println(p2.getName()); //bean转换Map,describe方法 MapbeanMap = BeanUtils.describe(p); SetentrySet = beanMap.entrySet(); Iteratorit = entrySet.iterator(); while(it.hasNext()) { Map.Entryme = (Entry) it.next(); System.out.println(me.getKey()+":"+me.getValue()); } //可以这样搞看到没有,可以操作Map MapbeanMap2 = new TreeMap(); beanMap2.put("name","jissbon"); BeanUtils.setProperty(beanMap2,"name", "xxxxxx"); //Map灌装到bean中,populate方法 BeanUtils.populate(p2,beanMap2); System.out.println(p2.getName()); } } >>PropertyUtils工具 也有和BeanUtils一样的setProperty方法,这里不再赘述。