Java核心_內省
查看java的api,發現有一個包java.bean咦,這個包是干什么的呢,原來,它是用來操作JavaBean對象的!
一、內省操作①JavaBean:一種特殊的Java類無參構造方法,每個屬性提供getter和setter/Introspector/src/yuki/core/introspector/bean/Point.java
package yuki.core.introspector.bean;public class Point { PRivate int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; }}獲取設置值
用內省獲取屬性值與設置屬性值/Introspector/src/yuki/core/introspector/test/PointTest1
package yuki.core.introspector.test;import java.beans.PropertyDescriptor;import java.lang.reflect.Method;import yuki.core.introspector.bean.Point;public class PointTest { /** * 獲得point對象的getX方法的值 * 如果用反射,需要得到x的字段名 * 然后首字母大寫,前面加get,拼成getX * 然后調用這個對象的方法拿到x屬性 * 這里不演示 * * 如果用內省的方法,可以...... * @throws Exception */ public static void main(String[] args) throws Exception { Point p = new Point(3, 4); String propertyName = "x"; // x --> X --> getX --> MethodGetX PropertyDescriptor pd = new PropertyDescriptor(propertyName, p.getClass()); Method methodGetX = pd.getReadMethod(); Object retVal = methodGetX.invoke(p); System.out.println(retVal); Method methodSetX = pd.getWriteMethod(); methodSetX.invoke(p, 7); System.out.println(p.getX()); }}
運行結果如下:
37
②抽取方法使用Eclipse從代碼中抽取出方法Refractor>Extract Method...>MethodName=
/Introspector/src/yuki/core/introspector/test/PointTest2
package yuki.core.introspector.test;import java.beans.IntrospectionException;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import yuki.core.introspector.bean.Point;public class PointTest { public static void main(String[] args) throws Exception { Point p = new Point(3, 4); String propertyName = "x"; Object retVal = getProperty(p, propertyName); System.out.println(retVal); Object value = 7; setProperty(p, propertyName, value); System.out.println(p.getX()); } private static void setProperty(Object p, String propertyName, Object value) throws IntrospectionException, IllegalaccessException, InvocationTargetException { PropertyDescriptor pd2 = new PropertyDescriptor(propertyName, p.getClass()); Method methodSetX = pd2.getWriteMethod(); methodSetX.invoke(p, value); } private static Object getProperty(Object p, String propertyName) throws IntrospectionException, IllegalAccessException, InvocationTargetException { PropertyDescriptor pd = new PropertyDescriptor(propertyName, p.getClass()); Method methodGetX = pd.getReadMethod(); Object retVal = methodGetX.invoke(p); return retVal; }}運行結果如下:
37
③BeanInfo對象調用IntroSpector.getBeanInfo可以得到BeanInfo對象,BeanInfo對象封裝了把這個類當作JavaBean看的結果信息/Introspector/src/yuki/core/introspector/test/PointTest3
package yuki.core.introspector.test;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 yuki.core.introspector.bean.Point;public class PointTest { public static void main(String[] args) throws Exception { Point p = new Point(3, 4); String propertyName = "x"; Object retVal = getProperty(p, propertyName); System.out.println(retVal); } private static Object getProperty(Object p, String propertyName) throws IntrospectionException, IllegalAccessException, InvocationTargetException { BeanInfo beanInfo = Introspector.getBeanInfo(p.getClass()); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); Object retVal = null; for(PropertyDescriptor pd : pds){ if(pd.getName().equals(propertyName)){ Method methodGetX = pd.getReadMethod(); retVal = methodGetX.invoke(p); break; } } return retVal; }}運行結果如下:
3
二、BeanUtils工具包操作JavaBean①Apache提供的工具包http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgicommons-beanutils-1.9.2-bin.zip/commons-beanutils-1.9.2.jar
報錯:java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory還需要提供日志包:commons-logging-1.1.3.jar再次運行得到x的值為3,設置x的值為9/Introspector/src/yuki/core/introspector/test/PointTest.java
package yuki.core.introspector.test;import org.apache.commons.beanutils.BeanUtils;import yuki.core.introspector.bean.Point;public class PointTest { public static void main(String[] args) throws Exception { Point p = new Point(3, 4); String x = BeanUtils.getProperty(p, "x"); System.out.println(x); BeanUtils.setProperty(p, "x", 9); System.out.println(p.getX()); System.out.println(BeanUtils.getProperty(p, "x").getClass().getName()); }}運行結果如下:
39java.lang.String
字符串類型與屬性類型的自動轉換但是,得到x的結果類型為字符串,但是實際值為int因為從瀏覽器中獲取的值是字符串,如果設置的是"9"的字符串,就會自動轉換成int而顯示在網頁上的值也是是字符串,所以,這樣的設定提供了很大的便捷
②屬性的級聯操作假設有一個屬性是日期類型類Date有一個方法,setTime(long time);所以可以認為Date有一個time的屬性屬性birth是一個復合屬性,所以可以Date的毫秒值直接獲取cat.getBirth()得到的是null,這是因為沒有給birth對象賦初值;/Introspector/src/yuki/core/introspector/bean/Cat.java
package yuki.core.introspector.bean;import java.util.Date;public class Cat { private Date birth; private String name; private Integer age; public Cat() {} public Cat(Date birth) { this.birth = birth; } public Cat(Date birth, String name, Integer age) { this.birth = birth; this.name = name; this.age = age; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Cat [birth=" + birth + ", name=" + name + ", age=" + age + "]"; } }/Introspector/src/yuki/core/introspector/test/CatTest.java
package yuki.core.introspector.test;import java.util.Date;import org.apache.commons.beanutils.BeanUtils;import yuki.core.introspector.bean.Cat;public class CatTest { public static void main(String[] args) throws Exception { Cat cat = new Cat(); cat.setBirth(new Date()); BeanUtils.setProperty(cat, "birth.time", "10001000"); System.out.println(cat.getBirth()); String birth_time = BeanUtils.getProperty(cat, "birth.time"); System.out.println(birth_time); }}運行結果如下:
Thu Jan 01 10:46:41 CST 197010001000
③BeanUtils的函數
一個對象上的屬性拷貝到另外一個對象public static void copyProperties(Object dest, Object orig)一個JavaBean的屬性轉換成Mappublic static Map<String,String> describe(Object bean)Map轉換成一個JavaBean的屬性public static void populate(Object bean, Map<String,? extends Object> properties)/Introspector/src/yuki/core/introspector/map/BeanUtilsTest.java
package yuki.core.introspector.map;import java.util.Date;import java.util.HashMap;import java.util.Map;import org.apache.commons.beanutils.BeanUtils;import yuki.core.introspector.bean.Cat;public class BeanUtilsTest { public static void main(String[] args) throws Exception { //Map --> JavaBean Cat cat = new Cat(); Map<String, Object> map = new HashMap<String, Object>(); map.put("name", "Tom"); map.put("age", 12); BeanUtils.populate(cat, map); System.out.println(cat); //JavaBean --> Map Map<String, String> map2 = BeanUtils.describe(cat); for(Map.Entry<String, String> entry : map2.entrySet()){ System.out.println(entry.getKey() + " -> " + entry.getValue()); } //cat --> cat2 Cat cat2 = new Cat(new Date(), null, 14); BeanUtils.copyProperties(cat2, cat); System.out.println(cat2); }}運行結果如下:
Cat [birth=null, name=Tom, age=12]name -> Tombirth -> nullclass -> class yuki.core.introspector.bean.Catage -> 12Cat [birth=null, name=Tom, age=12]
④PropertyUtils的函數這個對象的函數setProperty和getProperty的類型轉換是沒有字符串的/Introspector/src/yuki/core/introspector/map/PropertyUtilsTest.java
package yuki.core.introspector.map;import org.apache.commons.beanutils.PropertyUtils;import yuki.core.introspector.bean.Cat;public class PropertyUtilsTest { public static void main(String[] args) throws Exception { Cat cat = new Cat(); PropertyUtils.setProperty(cat, "age", 11); System.out.println(cat); System.out.println(PropertyUtils.getProperty(cat, "age").getClass().getName()); }}運行結果如下:
Cat [birth=null, name=null, age=11]java.lang.Integer
以上的內容參考了[張孝祥Java高新技術_內省]
三、用同一個類的對象更新這個對象的屬性一般用作表單中取得的對象更新數據庫中的對象①反射的方式spring的 @Autowire標簽可以不用寫setter方法就可以實現自動編織
/Introspector/src/yuki/core/introspector/field/FieldUtil.java
package yuki.core.introspector.field;import java.lang.reflect.Field;import java.util.Date;import yuki.core.introspector.bean.Cat;public class FieldUtil { public static void main(String[] args) throws Exception { Cat c1 = new Cat(new Date(12345), "Tom", 11); Cat c2 = new Cat(); FieldUtil.updateField(c1, c2); System.out.println(c1); c1 = new Cat(new Date(12345), "Tom", 11); c2 = new Cat(new Date(), "", null); FieldUtil.updateField(c1, c2); System.out.println(c1); c1 = new Cat(new Date(12345), "Tom", 11); c2 = new Cat(new Date(), "Gaffey", null); FieldUtil.updateField(c1, c2); System.out.println(c1); c1 = new Cat(new Date(12345), "Tom", 11); c2 = new Cat(null, "Gaffey", 13); FieldUtil.updateField(c1, c2); System.out.println(c1); } /** * 用同一個類的對象更新這個對象的屬性 * @param dest 目標對象,一般屬數據庫中取出的的對象 * @param orig 賦值對象,一般是表單中取得的對象 * @throws IllegalAccessException * @throws IllegalArgumentException */ public static <T> void updateField(T dest, T orig) throws IllegalArgumentException, IllegalAccessException { Field[] fs = dest.getClass().getDeclaredFields(); for(Field f : fs){ try { f.setAccessible(true); Object val = f.get(orig); if(val != null && !"".equals(val)){ f.set(dest, val); } } finally { f.setAccessible(false); } } }}運行結果如下:
Cat [birth=Thu Jan 01 08:00:12 CST 1970, name=Tom, age=11]Cat [birth=Sat Oct 18 01:56:21 CST 2014, name=Tom, age=11]Cat [birth=Sat Oct 18 01:56:21 CST 2014, name=Gaffey, age=11]Cat [birth=Thu Jan 01 08:00:12 CST 1970, name=Gaffey, age=13]
②內省的方式/Introspector/src/yuki/core/introspector/field/PropertyUtil.java
package yuki.core.introspector.field;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 java.util.Date;import yuki.core.introspector.bean.Cat;public class PropertyUtil { public static void main(String[] args) throws Exception { Cat c1 = new Cat(new Date(12345), "Tom", 11); Cat c2 = new Cat(); PropertyUtil.updateProperty(c1, c2); System.out.println(c1); c1 = new Cat(new Date(12345), "Tom", 11); c2 = new Cat(new Date(), "", null); PropertyUtil.updateProperty(c1, c2); System.out.println(c1); c1 = new Cat(new Date(12345), "Tom", 11); c2 = new Cat(new Date(), "Gaffey", null); PropertyUtil.updateProperty(c1, c2); System.out.println(c1); c1 = new Cat(new Date(12345), "Tom", 11); c2 = new Cat(null, "Gaffey", 13); PropertyUtil.updateProperty(c1, c2); System.out.println(c1); } /** * 用同一個類的對象更新這個對象的屬性 * @param dest 目標對象,一般屬數據庫中取出的的對象 * @param orig 賦值對象,一般是表單中取得的對象 * @throws IntrospectionException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static <T> void updateProperty(T dest, T orig) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { BeanInfo beanInfo = Introspector.getBeanInfo(dest.getClass()); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for(PropertyDescriptor pd : pds){ Method read = pd.getReadMethod(); Object val = read.invoke(orig); if(val != null && !"".equals(val)){ Method write = pd.getWriteMethod(); if(write != null) write.invoke(dest, val); } } }}運行結果如下:
Cat [birth=Thu Jan 01 08:00:12 CST 1970, name=Tom, age=11]Cat [birth=Sat Oct 18 01:57:35 CST 2014, name=Tom, age=11]Cat [birth=Sat Oct 18 01:57:35 CST 2014, name=Gaffey, age=11]Cat [birth=Thu Jan 01 08:00:12 CST 1970, name=Gaffey, age=13]
本文的目錄結構:

更多好文請關注:http://www.survivalescaperooms.com/kodoyang/
請點擊下方紅色的"關注我",關注我吧!
kongdongyang2014/10/18
新聞熱點
疑難解答