BeanUtils.copyProperties引發(fā)的血案
在一次使用BeanUtils.copyProperties的方法是,莫名其妙的報(bào)錯(cuò),產(chǎn)生的代碼分解如下:

把EntityA的值賦值給EntityB:

在運(yùn)行這段代碼的時(shí)候,發(fā)生了異常的信息:
對(duì)于這個(gè)異常,我觀察了很久,在調(diào)試的時(shí)候發(fā)現(xiàn),EntityA中的UniteA中的字段竟然能夠賦值給 EntityB中UnitB中的字段!! 類型不一樣,竟能夠存儲(chǔ)!!
泛型僅僅適用于編譯期
對(duì)于這個(gè)問題,歸根于Java的泛型的特點(diǎn),泛型僅僅適用于編譯期,下面我們寫幾個(gè)代碼來驗(yàn)證這個(gè)問題:

上面的例子我們可以看到List的類型的集合無法直接添加一個(gè)整型數(shù)據(jù),但這個(gè)僅僅在編譯的才校驗(yàn),我們可以是有反射繞過這個(gè)驗(yàn)證。

調(diào)試信息如下:
同樣,我們也可以使用如下代碼驗(yàn)證上面的結(jié)論:

打印結(jié)果為:true
補(bǔ)充
除BeanUtils外還有一個(gè)名為PropertyUtils的工具類,它也提供copyProperties()方法,作用與 BeanUtils的同名方法十分相似,主要的區(qū)別在于后者提供類型轉(zhuǎn)換功能,即發(fā)現(xiàn)兩個(gè)JavaBean的同名屬性為不同類型時(shí),在支持的數(shù)據(jù)類型范圍內(nèi)進(jìn)行轉(zhuǎn)換,而前者不支持這個(gè)功能,但是速度會(huì)更快一些。BeanUtils支持的轉(zhuǎn)換類型如下:
- java.lang.BigDecimal
- java.lang.BigInteger
- boolean and java.lang.Boolean
- byte and java.lang.Byte
- char and java.lang.Character
- java.lang.Class
- double and java.lang.Double
- float and java.lang.Float
- int and java.lang.Integer
- long and java.lang.Long
- short and java.lang.Short
- java.lang.String
- java.sql.Date
- java.sql.Time
- java.sql.Timestamp
這里要注意一點(diǎn),java.util.Date是不被支持的,而它的子類java.sql.Date是被支持的。因此如果對(duì)象包含時(shí)間類型的屬性,且希望被轉(zhuǎn)換的時(shí)候,一定要使用java.sql.Date類型。否則在轉(zhuǎn)換時(shí)會(huì)提示argument mistype異常。
優(yōu)缺點(diǎn):
Apache Jakarta Commons項(xiàng)目非常有用。我曾在許多不同的項(xiàng)目上或直接或間接地使用各種流行的commons組件。其中的一個(gè)強(qiáng)大的組件就是BeanUtils。我 將說明如何使用BeanUtils將local實(shí)體bean轉(zhuǎn)換為對(duì)應(yīng)的value 對(duì)象:
BeanUtils.copyProperties(aValue, aLocal)
上面的代碼從aLocal對(duì)象復(fù)制屬性到aValue對(duì)象。它相當(dāng)簡(jiǎn)單!它不管local(或?qū)?yīng)的value)對(duì)象有多少個(gè)屬性,只管進(jìn)行復(fù)制。我們假設(shè) local對(duì)象有100個(gè)屬性。上面的代碼使我們可以無需鍵入至少100行的冗長(zhǎng)、容易出錯(cuò)和反復(fù)的get和set方法調(diào)用。這太棒了!太強(qiáng)大了!太有用 了!
現(xiàn)在,還有一個(gè)壞消息:使用BeanUtils的成本驚人地昂貴!我做了一個(gè)簡(jiǎn)單的測(cè)試,BeanUtils所花費(fèi)的時(shí)間要超過取數(shù) 據(jù)、將其復(fù)制到對(duì)應(yīng)的 value對(duì)象(通過手動(dòng)調(diào)用get和set方法),以及通過串行化將其返回到遠(yuǎn)程的客戶機(jī)的時(shí)間總和。所以要小心使用這種威力!