在我們實際項目開發過程中,我們經常需要将不同的兩個對象執行個體進行屬性複制,進而基于源對象的屬性資訊進行後續操作,而不改變源對象的屬性資訊,比如dto資料傳輸對象和資料對象do,我們需要将do對象進行屬性複制到dto,但是對象格式又不一樣,是以我們需要編寫映射代碼将對象中的屬性值從一種類型轉換成另一種類型。
在具體介紹兩種 beanutils 之前,先來補充一些基礎知識。它們兩種工具本質上就是對象拷貝工具,而對象拷貝又分為深拷貝和淺拷貝,下面進行詳細解釋。
在java中,除了 基本資料類型之外,還存在 類的執行個體對象這個引用資料類型,而一般使用 “=”号做指派操作的時候,對于基本資料類型,實際上是拷貝的它的值,但是對于對象而言,其實指派的隻是這個對象的引用,将原對象的引用傳遞過去,他們實際還是指向的同一個對象。
而淺拷貝和深拷貝就是在這個基礎上做的區分,如果在拷貝這個對象的時候,隻對基本資料類型進行了拷貝,而對引用資料類型隻是進行引用的傳遞,而沒有真實的建立一個新的對象,則認為是淺拷貝。反之,在對引用資料類型進行拷貝的時候,建立了一個新的對象,并且複制其内的成員變量,則認為是深拷貝。
簡單來說:
淺拷貝:對基本資料類型進行值傳遞,對引用資料類型進行引用傳遞般的拷貝,此為淺拷貝
深拷貝:對基本資料類型進行值傳遞,對引用資料類型,建立一個新的對象,并複制其内容,此為深拷貝。
前面簡單講了一下對象拷貝的一些知識,下面就來具體看下兩種 beanutils 工具
首先來看一個非常簡單的beanutils的例子
從上面的例子可以看出,對象拷貝非常簡單,beanutils最常用的方法就是:
但是由于 apache下的beanutils對象拷貝性能太差,不建議使用,而且在阿裡巴巴java開發規約插件上也明确指出:
ali-check | 避免用apache beanutils進行屬性的copy。
commons-beantutils 對于對象拷貝加了很多的檢驗,包括類型的轉換,甚至還會檢驗對象所屬的類的可通路性,可謂相當複雜,這也造就了它的差勁的性能,具體實作代碼如下:
使用spring的beanutils進行對象拷貝:
spring下的beanutils也是使用 copyproperties方法進行拷貝,隻不過它的實作方式非常簡單,就是對兩個對象中相同名字的屬性進行簡單的get/set,僅檢查屬性的可通路性。具體實作如下:
可以看到,成員變量指派是基于目标對象的成員清單,并且會跳過ignore的以及在源對象中不存在,是以這個方法是安全的,不會因為兩個對象之間的結構差異導緻錯誤,但是必須保證同名的兩個成員變量類型相同
以上簡要的分析兩種beanutils,因為apache下的beanutils性能較差,不建議使用,可以使用 spring的beanutils ,或者使用其他拷貝架構,比如:dozer、modelmapper等等,在後面的文章中我會對這些拷貝架構進行介紹。
-end-
如果看到這裡,說明你喜歡這篇文章,請 轉發、點贊。同時 标星(置頂)本公衆号可以第一時間接受到博文推送。
最近整理一份面試資料《java技術棧學習手冊》,覆寫了java技術、面試題精選、spring全家桶、nginx、ssm、微服務、資料庫、資料結構、架構等等。
擷取方式:點“ 在看,關注公衆号 java後端 并回複 777 領取,更多内容陸續奉上。
喜歡文章,點個在看