最常見的是, 兩個物件有幾乎相仿的 setter/getter methods 情形下進行 copy;在很早的 COBOL、FoxBase ... 年代, 這些 language 在宣告上或語法上已有支援, 而 4GL 年代也有相同、類似的支援方式:
LET recordA. * = recordB.*唯獨當年剛從 internet 中展露頭角的 Java 還沒有"方便"的方式, 尤其是當兩個物件有幾十、甚至上百個 attributes 時, programmer 一定會恨死如:
... beanA.setAttr1(beanB.getAttr1()); beanA.setAttr2(beanB.getAttr2()); beanA.setAttr3(beanB.getAttr3()); ... beanA.setAttr99(beanB.getAttr99()); ...這種佔篇幅、又容易打(或複製)錯字而不易察覺的笨挫寫法。
此時, programmer 一定會很感激 BeanUtils 的存在; 它的其中一個最基本的功能:
BeanUtils.copyProperties(destBean, origBean);它會取得 origBean 中所有 public getXXX() 之類的 methods 回傳值, 找到 destBean 中相對應的 setXXX() methods, 接著叫(調)用並賦值給它。(當然, origBean 的 getter 回傳型別與對應 destBean 的 setter 參數型別要相容)
當有十幾、廿個 attributes 要賦值, 但僅少數幾個則否; 那要怎樣進行呢?
可從 BeanUtils 的 source code 看來, 它主要是由 BeanUtilsBean class 的 method 進行 copy 功能:
public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException { // ... copyProperty(dest, name, value); // ... }所以, 只要製訂這 class 新的 subclass, 並控制 copyProperty() 的處理, 如下所示:
@Override public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { if (!excludeNames.contains(name)) { super.copyProperty(bean, name, value); } }而在其中, 只要先紀錄 excludeNames 即可。
但, 如果沒有重用(re-use)的情形, 定義新的 class 實在會顯得 Java 語言的繁瑣; 索性, 可利用 anonymous inner class 寫法來做就好:
// ... new BeanUtilsBean() { private List〈string〉 excludeNames = new ArrayList〈string〉(0); BeanUtilsBean setExcludeNames(String[] excludeNames) { if (excludeNames != null && excludeNames.length > 0) { this.excludeNames = Arrays.asList(excludeNames); } return this; } @Override public void copyProperty(Object bean, String name, Object value) throws IllegalAccessException, InvocationTargetException { if (!excludeNames.contains(name)) { super.copyProperty(bean, name, value); } } }.setExcludeNames(new String[] {"someAttr"}) .copyProperties(destBean, origBean); // ...如此直接叫(調)用即可。
而其中 setExcludeNames() 回傳 this 的方法, 可以免除自定 class 及其新的 constructor 來紀錄 excludeNames 的麻煩。
沒有留言:
張貼留言