---------------
ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ---------------
第一 反射
一、概述:反射就是把java类中的各个成员映射成相应的java类。简单的说就是取出类的各个成分,然后对其进行操作,这种技术一般用于框架。
1、Class是Java程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。
2、Class和class的区别
1)class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。
2)Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类。
3、反射的步骤:
1)加载类
2)确定要反射的对象(字段、构造方法、方法)
3)建立具体的反射
二、对象的创建和使用:
1、创建实例对象:不可用new Class()的方式,因为Class没有这样的构造方法。而是将字节码对象赋值给Class变量。方式有如下三种:
①、Class clazz = Class.forName("enhance.test.reflect.Person");参数是类完整的路径。
②、Class clazz = new Person().getClass();这种方式是通过类的对象的getClass方法获取类的字节码。
③、Class clazz3 = Person.class;第三种则是通过类名直接获取类的字节码。
说明:
1)此类已经加载进内存:不需要再加载,直接获取字节码。
2)此类还未加载进内存:先加载类,然后再获取字节码。
3)每个类的字节码对象只有唯一的一个
2、九个预定义的Class:
1)包括八种基本类型(byte、short、int、long、float、double、char、boolean)的字节码对象和一种返回值为void类型的void.class。
2)Integer.TYPE是Integer类的一个常量,它代表此包装类型包装的基本类型的字节码,所以和int.class是相等的。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示
3)数组类型的Class实例对象,可以用Class.isArray()方法判断是否为数组类型的。
3、任何类型都有各自的Class实例对象,如int[].class、void.class等。
@Test//junit测试,方法可以独立运行 public void testz() throws Exception { String str = "ab"; String str1 = new String("155"); Class cls = str1.getClass(); Class cls1 = Class.forName("java.lang.String"); Class cls2 = str.getClass(); Class cls3 = String.class; System.out.println("cls == cls2" + (cls == cls2)); System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); System.out.println(cls1.isPrimitive()); System.out.println(int.class.isPrimitive()); System.out.println(int.class == Integer.class); // Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, // Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE System.out.println(int.class == Integer.TYPE);// Integer.TYPE获取基本数据类型 System.out.println(int[].class.isPrimitive()); System.out.println(int[].class.isArray()); System.out.println(void.class.isArray()); } /* * 把字段中String类型的b全部替换成a */ @Test public void change() throws Exception{ Class clazz = Class.forName("enhance.test.reflect.Person"); Person p = new Person(); Field[] fields = clazz.getFields(); for(Field field : fields){ if(field.getType() == String.class){//字节码在内存中是相同的,所以用== String oldStr = (String) field.get(p); String newStr = oldStr.replace('b', 'a'); field.set(p, newStr); System.out.println(field.get(p)); } } }
三、反射构造函数:
1、用到的方法:
(public)getConstructor(Class<?>... parameterTypes)返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
(private)getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
2、为什么反射出类的构造方法:反射出类的构造方法无非就是用于创建对象
3、反射构造函数的步骤:
①、加载类,有三种方式可选,最常见的是通过Class的静态forName()方法加载。
②、通过Class的对象的getConstructor或getDeclaredConstructor方法对指定的构造函数进行反射
③、如果是私有的需要通过第二步返回的Constructor对象的setAccessible(true)方法打开其访问权限,这种方式称为暴力反射
④、通过第二步返回的Constructor对象的newInstance方法创建对象
⑤、对其对象进行相对应的操作
4、反射常见的构造函数:
被反射的类:
public class Person { public String aa = "abaaaa"; public String ba = "bbbbbaaa"; private int age = 25; private static int password = 123; public final static int IN = 1212; public Person() { System.out.println("person"); } public Person(String name) { System.out.println("person name:" + name); } public Person(String name, int age) { System.out.println("person name age" + name + age); } private Person(List list) { System.out.println("person list"); } public void methodDemo() { System.out.println("11"); } public void methodDemo(String name, int age) { System.out.println(name + age); } public Class[] methodDemo(String name, int[] age) { return new Class[] { String.class }; } private void methodDemo(InputStream in) { System.out.println(in); } public static void methodDemo(int num) { System.out.println(num); } public static void main(String[] args) { System.out.println("main"); } }
反射构造函数:
/* * 反射构造函数 */ public class Demo { /* * 反射无参的构造函数 :public Person() 得到构造函数无非就是用于创建对象 */ @Test public void test1() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person");// 加载类 Constructor<Person> c = clazz.getConstructor(null);// 反射无参的构造函数,不传参 Person p = c.newInstance(null);// 创建对象 System.out.println(p.aa); } /* * 反射有参数的构造函数 public Person(String name) */ @Test public void test2() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person"); // 反射有参数的构造函数,传递所需的对象 Constructor<Person> c = clazz.getConstructor(String.class); Person p = c.newInstance("xxxxxxxx"); System.out.println(p.aa); } /* * 反射有参数的构造函数 public Person(String name,int age) */ @Test public void test3() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person"); Constructor<Person> c = clazz.getConstructor(String.class, int.class);// java中任何东西都是用一个class来表示的 Person p = c.newInstance("zhangsan", 200); System.out.println(p.aa); } /* * 反射有参数的构造函数 private Person(List list) getDeclaredConstructor反射私有 */ @Test public void test4() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person"); // 反射私有的构造函数 Constructor<Person> c = clazz.getDeclaredConstructor(List.class); c.setAccessible(true);// 暴力反射,这样才能访问到private Person p = c.newInstance(new ArrayList()); System.out.println(p.aa); } /* * 创建对象的另一种途径,等效于test1 */ @Test public void test5() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person"); // 通过Class对象直接创建对象,这里其实是调用的是无参的构造函数 Person p = (Person) clazz.newInstance(); System.out.println(p.aa); } }
四、反射类中的方法:
1、用到的方法:
(public)getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
(private)getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
2、为什么反射出类的方法:反射出类的方法无非就是让方法运行
3、反射类的方法的步骤:
①、加载类,有三种方式可选,最常见的是通过Class的静态forName()方法加载。
②、通过Class的对象的getMethod或getDeclaredMethod方法对指定的方法进行反射
③、如果是私有的需要通过第二步返回的Method对象的setAccessible(true)方法打开其访问权限,这种方式称为暴力反射
④、通过第二步返回的Method对象的invoke方法让类中被反射出来的方法运行
4、反射常见的方法:
/* * 反射方法 */ public class Demo2 { /* * public void methodDemo() */ @Test public void test1() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Method m = clazz.getMethod("methodDemo", null);// 方法名,参数 m.invoke(p, null);// 对象,参数 } /* * public void methodDemo(String name,int age) */ @Test public void test2() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Method m = clazz.getMethod("methodDemo", String.class, int.class); m.invoke(p, "jdi", 40); } /* * public Class[] methodDemo(String name,int[] age) */ @Test public void test3() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Method m = clazz.getMethod("methodDemo", String.class, int[].class); Class[] cls = (Class[]) m.invoke(p, "zhang", new int[] { 1, 2, 3 }); System.out.println(cls[0]); } /* * private void methodDemo(InputStream in) */ @Test public void test4() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Method m = clazz.getDeclaredMethod("methodDemo", InputStream.class); m.setAccessible(true); m.invoke(p, new FileInputStream("c:\\1.jpg")); } /* * public static void methodDemo(int num) */ @Test public void test5() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person"); Method m = clazz.getMethod("methodDemo", int.class); m.invoke(null, 54);// 静态不需要对象 } /* * 主函数: public static void main(String[] args) */ @Test public void test6() throws Exception { Class clazz = Class.forName("enhance.test.reflect.Person"); Method m = clazz.getMethod("main", String[].class); //二选一,为了兼容以前的版本,所以main方法这里需要经传递的数组惊醒包装 m.invoke(null, new Object[]{new String[]{"aa","bb"}}); m.invoke(null, (Object)new String[]{"aa","bb"}); //JDK1.5 Method的invoke(Object obj, Object... args)obj方法所属的对象,args参数 //JDK1.4 Method的invoke(Object obj, Object obj[])obj方法所属的对象,args参数 //public void methodDemo(String name,int age) //1.4 method.inovke(obj,new Object[]{"aaa","123"}); } }
五、反射字段:
1、用到的方法:
(public)getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
(private)getDeclaredField(String name)返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
2、为什么反射出类的字段:反射出类的字段无非就是要对数据进行操作包括取值和设定值
3、反射字段的步骤:
①、加载类,有三种方式可选,最常见的是通过Class的静态forName()方法加载。
②、通过Class的对象的getField或getDeclaredField方法对指定的构造函数进行反射
③、如果是私有的需要通过第二步返回的Field对象的setAccessible(true)方法打开其访问权限,这种方式称为暴力反射
④、通过第二步返回的Field对象的get和set方法分别对其进行取值和设定值的操作
⑤、对其对象进行相对应的操作
4、反射常见的字段:
/* * 反射字段 */ public class Demo3 { /* * public String aa = "aaaaaa"; */ @Test public void test1() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Field f = clazz.getField("aa"); // 获取字段的值 Object value = f.get(p);// 传入对象 // 获取字段的类型 Class type = f.getType(); if (type.equals(String.class)) { String str = (String) value; System.out.println(str); } // 设置字段的值 f.set(p, "xxxxxxxxxxxxxxxxxxxxxxxxx"); System.out.println(p.aa); } /* * private int age; */ @Test public void test2() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Field f = clazz.getDeclaredField("age"); f.setAccessible(true); System.out.println(f.get(p)); } /* * private static int = 123; */ @Test public void test3() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Field f = clazz.getDeclaredField("password"); f.setAccessible(true); System.out.println(f.get(p)); } /* * public final static int IN = 1212; */ @Test public void test4() throws Exception { Person p = new Person(); Class clazz = Class.forName("enhance.test.reflect.Person"); Field f = clazz.getDeclaredField("IN"); // f.set(p, "1111111111");//不能对final修饰变量再次赋值 System.out.println(f.get(p)); } }
六、HashSet和与hashCode的分析
示例:
import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public class ReflectTest2 { public static void main(String [] args){ Collection cons = new HashSet(); ReflectPoint pt1 = new ReflectPoint(3,3); ReflectPoint pt2 = new ReflectPoint(5,5); ReflectPoint pt3 = new ReflectPoint(3,3); cons.add(pt1); cons.add(pt2); cons.add(pt3); cons.add(pt1); cons.remove(pt1); System.out.println(cons.size()); } } public class ReflectPoint { private int x; public int y; public String str1 = "ball"; public String str2 = "basketball"; public String str3 = "itcast"; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; //System.out.println("demo...");//测试 return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReflectPoint other = (ReflectPoint) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } public String toString(){ return str1+";" + str2 + ";" + str3; } }
覆写hashCode()方法的意义:只有存入的是具有hashCode算法的集合的,覆写hashCode()方法才有价值。
1、哈希算法的由来:
若在一个集合中查找是否含有某个对象,通常是一个个的去比较,找到后还要进行equals的比较,对象特别多时,效率很低,通过哈希算法,将集合分为若干个区域,每个对象算出一个哈希值,可将哈希值分组(一般模32为一组),每组对应某个存储区域,依一个对象的哈希码即可确定此对象对应区域,从而减少每个对象的比较,只需在指定区域查找即可,从而提高从集合中查找元素的效率。
示意图:
2、如果不存入是hashCode算法的集合中,那么则不用复写此方法。
3、只有类的实例对象要被采用哈希算法进行存入和检索时,这个类才需要按要求复写hashCode()方法,即使程序可能暂时不会用到当前类的hashCode()方法,但是为提供一个hashCode()方法也不会有什么不好,没准以后什么时候就会用到这个方法,所以通常要求hashCode()和equals()两者一并被覆盖。
4、提示:
1)若同类两对象用equals()方法比较的结果相同时,他们的哈希码也必须是相等的,但反过来就不成立了,如”BB”和”Aa”两字符串用equals()比较式不相等的,但是他们的哈希值是相等的。
2)当一个对象被存储进HashSet集合中,就不能再修改参与计算哈希值的字段,否则对象被修改后的哈希值与最初被存入的HashSet集合中的哈希值就不同了。在这种情况下,即使contains()方法是用对象的当前引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
简单说,之前存入的对象和修改后的对象,是具有不同的哈希值,被认为是不同的两个对象,这样的对象不再使用,又不移除,而越来越多,就会导致内存泄露。
补充:
内存泄露:某些对象不再使用了,占用着内存空间,并未被释放,就会导致内存泄露;也就是说当程序不断增加对象,修改对象,删除对象,日积月累,内存就会用光了,就导致内存溢出。
3)对象在调用方法时,对象会先进行一次自身hashCode()方法的调用,再进行操作方法。
七、反射在实际开发中的作用:
一、概述:反射一般是用于框架中
1、框架:通过反射调用位置Java类的一种方式。
如房地产商造房子用户住,门窗和空调等等内部都是由用户自己安装,房子就是框架,用户需使用此框架,安好门窗等放入到房地产商提供的框架中。
框架和工具类的区别:工具类被用户类调用,而框架是调用用户提供的类。
2、框架机器要解决的核心问题:
我们在写框架(造房子的过程)的时候,调用的类(安装的门窗等)还未出现,那么,框架无法知道要被调用的类名,所以在程序中无法直接new其某个类的实例对象,而要用反射来做。
3、简单框架程序的步骤:
1)右击项目名-->File-->命名config.properties的文件,写入键值对:className=java.util.ArrayList,等号右边的可以自己定义集合的名称,即用户可以对此记事本修改成自己的类名。
2)代码实现,加载此文件:
①将文件读取到读取流中,一定要用完整的路径,可以使用getRealPath()方法获取路径名,再加上自己定义的文件夹名。
②用Properties类的load()方法将流加载经内存,即提取文件中的信息。
③关闭流:关闭的是读取流,因为流中的数据已经加载进内存。
3)通过getProperty()方法获取类名属性,将传入的类名赋值给指定变量。
4)用反射的方式,创建对象newInstance()
5)进行相关的具体操作。
二、类加载器:
1、简述:类加载器是将.class的文件加载进内存,也可将普通文件中的信息加载进内存。
2、文件的加载问题:
1)eclipse会将源程序中的所有.java文件加载成.class文件,以确保编译,然后放到classPath指定的目录中去。并且会将非.java文件原封不动的复制到.class指定的目录中去。在真正编译的时候,使用classPath目录中的文件,即放置.class文件的目录。
2)写完程序是要讲配置文件放到.class文件目录中一同打包,这些都是类加载器加载的,资源文件(配置文件)也同样加载了配置文件。
3)框架中的配置文件都要放到classPath指定的文件夹中,原因是它的内部就是用类加载器加载的文件。
3、资源文件的加载:是使用类加载器。
1)由类加载器ClassLoader的一个对象加载经内存,即用getClassLoader()方法加载。若要加载普通文件,可用getResourseAsStream(String name)在classPath的文件中逐一查找要加载的文件。
2)在.class身上也提供了方法来加载资源文件,其实它内部就是先调用了Loader方法,再加载的资源文件。
如:Reflect.class.getResourseAsStream(String name)
4、配置文件的路径问题:
第一、用绝对路径,通过getRealPath()方法运算出来具体的目录,而不是内部编码出来的。
一般先得到用户自定义的总目录,在加上自己内部的路径。可以通过getRealPath()方法获取文件路径。对配置文件修改是需要要储存到配置文件中,那么就要得到它的绝对路径才行,因此,配置文件要放到程序的内部。
第二、配置路径问题:
①如果配置文件和classPath目录没关系,就必须写上绝对路径,
②如果配置文件和classPath目录有关系,即在classPath目录中或在其子目录中(一般是资源文件夹resource),那么就得写相对路径,因为它自己了解自己属于哪个包,是相对于当前包而言的。
public class FrameDemo { public static void main(String[] args) throws Exception { /* * 1、配置文件的路径必须是完整的路径,但完整的路径不是硬编码,而是运算出来的 * 配置文件的路径需在程序内部 */ // InputStream in = new FileInputStream("config.properties"); /* * 2、通过类加载器加载 * 但是配置文件属性是只读的,就是不能将文件写出(就是没有OutputStream) */ // InputStream in = FrameDemo.class.getClassLoader().getResourceAsStream( // "enhance/test/reflect/config.properties"); /* * 3、用自己的类加载 */ InputStream in = FrameDemo.class.getResourceAsStream("config.properties"); Properties pro = new Properties(); pro.load(in); in.close();//用完资源立马关闭,防止少量的内存泄露 String className = pro.getProperty("className"); //创建数组 Collection collection = (Collection) Class.forName(className).newInstance(); collection.add("123"); collection.add("354"); collection.add("123"); System.out.println(collection.size()); } }
第二 内省
一、概述:
内省主要针对JavaBean进行操作。
二、JavaBean(存在于java.bean包中)
1、简述:
1)JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法都符合某种特殊的命名规则。
2)它是一种特殊的Java类,其中的方法名称等,都符合特殊的规则。只要一个类中含有get和set打头的方法,就可以将其当做JavaBean使用。
3)字段和属性:
字段就是我们定义的一些成员变量,如private String name;等
而属性是具有某些功能,Bean属性,是含有get或set方法的那些属性的字段,即这个变量的get属性,set属性等。
2、作用:
如果要在两个模板之间传递多个信息,可将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO),这些信息在类中用私有字段来储存,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。
3、命名方式:
JavaBean的属性是根据其中的setter和getter方法来确定的,而不是依据其中的变量,如方法名为setId,则中文意思是设置Id,getId也是如此;去掉前缀,剩余部分就是属性名称,如果剩余部分的第二个字母小写,则把剩余部分改为小写。如:getAge/setAge-->age;gettime-->time;setTime-->time;getCPU-->CPU。
4、总之、一个类被当做JavaBean使用时,JavaBaan的属性是根据方法名推断出来的,它根本看不到Java类内部的成员变量。
5、JavaBean的好处:
一个符合JavaBean特点的类当做普通类一样可以使用,但是把它当做JavaBean类用肯定有好处的:
1)在JavaEE开发中,经常要使用JavaBean。很多环境就要求按JavaBean的方式进行操作。
2)JDK中提供了对JavaBean进行操作的API,这套API称为内省,若要自己通过getX的方式来访问私有x,可用内省这套API,操作JavaBean要比使用普通的方式更方便。
/* * 使用内省api操作bean的属性 */ public class IntrospectorDemo { /* * 得到类的属性 */ @Test public void test1() throws Exception { // BeanInfo info = Introspector.getBeanInfo(Book.class);//得到bean所有的属性,包含父类的 BeanInfo info = Introspector.getBeanInfo(Book.class, Object.class);// 得到本类所有的属性 PropertyDescriptor[] pds = info.getPropertyDescriptors();//得到所有的属性描述其 for (PropertyDescriptor pd : pds) { System.out.println(pd.getName());//取出所有的属性 } } /* * 操作bean的指定属性 */ @Test public void test2() throws Exception { Book b = new Book(); // 得到属性描述器 PropertyDescriptor dp = new PropertyDescriptor("name", Book.class); System.out.println(dp.getPropertyType());// 得到类型 // 设置值 Method method = dp.getWriteMethod();// public void setName(String name) method.invoke(b, "java"); // 获取值 method = dp.getReadMethod(); System.out.println(method.invoke(b, null));// public String getName() } }
第三 BeanUtils工具包
一、概述:
1、BeanUtils等工具包都是由Apache提供,为了便于开发。
2、BeanUtils可以将8种基本数据类型进行自动的转换,因此对于非基本数据类型,就需要注册转换器Converter,这就需要ConverUtils包
二、好处:
1、提供的set或get方法中,传入的是字符串,返回的还是字符串,因为在浏览器中,用户输入到文本框的都是以字符串的形式发送至服务器上的,所以操作的都是字符串。也就是说这个工具包的内部有自动将整数转换为字符串的操作。
2、支持属性的级联操作,即支持属性链。如可以设置:人的脑袋上的眼镜的眼珠的颜色。这种级联属性的属性连如果自己用反射,那就很困难了,通过这个工具包就可以轻松调用。
3、可以和Map集合进行相互转换:可将属性信息通过键值对的形式作为Map集合存储(通过staticjava.util.Map describe(java.lang.Object bean)的方法),也可以将Map集合转换为JavaBean中的属性信息(通过static void populate(java.lang.Object bean, java.util.Map properties)的方法)。
示例:
/* * 创建一个bean,专门用于封装数据 */ public class Person { private int password;// 字段 private String name;// 字段 private int age;// 字段 private Date birthday; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } /* * 一个bean的属性有她其中的get或set方法决定 * 现在这个bean中就有四个属性 本类四个继承Object一个getClass属性 */ public int getPassword() { return password; } public void setPassword(int password) { this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
/* * 使用beanutils操作bean的属性(第三方jar包) */ public class Demo { /* * 简单的操作 */ @Test public void test1() throws Exception { Person p = new Person(); // 通过BeanUtils设置属性 BeanUtils.setProperty(p, "name", "java book"); // 通过BeanUtils获取属性 System.out.println(BeanUtils.getProperty(p, "name")); } /* * 基本数据类型的自动匹配 * 只支持8种基本数据类型 */ @Test public void test2() throws Exception { String name = "xcc"; String password = "123"; String age = "23"; Person p = new Person(); BeanUtils.setProperty(p, "name", name); BeanUtils.setProperty(p, "password", password); BeanUtils.setProperty(p, "age", age); System.out.println(BeanUtils.getProperty(p, "name")); System.out.println(BeanUtils.getProperty(p, "password")); System.out.println(BeanUtils.getProperty(p, "age")); } /* * 自定义类型转化器 */ @Test public void teat3() throws Exception{ String name = "xcc"; String password = "123"; String age = "23"; String birthday = "1980-08-08"; //为了让日期赋到bean的birthday上,所以需要给BeanUtils注册一个日期转化器 ConvertUtils.register(new Converter() { @Override public Object convert(Class type, Object value) { if(value == null){ return null; } if(!(value instanceof String)){ new ConversionException("这里只支持String类型的转换"); } String str = (String) value; if(str.trim().equals("")){ return null; } SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); try { return df.parse(str); } catch (ParseException e) { new RuntimeException(e);//异常链不能断 } return null; } }, Date.class); Person p = new Person(); BeanUtils.setProperty(p, "name", name); BeanUtils.setProperty(p, "password", password); BeanUtils.setProperty(p, "age", age); BeanUtils.setProperty(p, "birthday", birthday); System.out.println(BeanUtils.getProperty(p, "name")); System.out.println(BeanUtils.getProperty(p, "password")); System.out.println(BeanUtils.getProperty(p, "age")); System.out.println(BeanUtils.getProperty(p, "birthday")); } /* * BeanUtils提供了很多转换器,一般情况下可以直接拿过来用的 */ @Test public void teat4() throws Exception{ String name = "xcc"; String password = "123"; String age = "23"; String birthday = "1980-08-08"; ConvertUtils.register(new DateLocaleConverter(), Date.class); Person p = new Person(); BeanUtils.setProperty(p, "name", name); BeanUtils.setProperty(p, "password", password); BeanUtils.setProperty(p, "age", age); BeanUtils.setProperty(p, "birthday", birthday); System.out.println(BeanUtils.getProperty(p, "name")); System.out.println(BeanUtils.getProperty(p, "password")); System.out.println(BeanUtils.getProperty(p, "age")); System.out.println(BeanUtils.getProperty(p, "birthday")); } /* * 用map集合填充bean的属性 */ @Test public void teat5() throws Exception{ Map<String,String> map = new HashMap<String,String>(); map.put("name", "zhangs"); map.put("password", "123"); map.put("age", "23"); map.put("birthday", "1989-01-02"); ConvertUtils.register(new DateLocaleConverter(), Date.class); Person p = new Person(); BeanUtils.populate(p, map);//将map中的值填充到bean中 System.out.println(BeanUtils.getProperty(p, "name")); System.out.println(BeanUtils.getProperty(p, "password")); System.out.println(BeanUtils.getProperty(p, "age")); System.out.println(BeanUtils.getProperty(p, "birthday")); } }