java对象的类型转换_Java对象的类型转换和属性复制
1. 問題的源由
在J2EE項目開發中,會涉及很多領域模型對象,例如,
VO (View Object) 視圖對象,也叫展示對象,用于前端頁面渲染所需要的數據
DTO (Data Transfer Object) 數據傳輸對象,一般用于Service和Manager向外傳輸數據
PO (Persistent Object) 持久化對象,一般和數據庫表結構會形成一一映射關系,通過DAO層向上傳輸數據源對象
更多領域分層模型,及其所在的應用分層,可見阿里巴巴Java開發手冊中的工程規約定義。
這些VO/DTO/PO都是POJO對象,每個屬性都有getter/setter方法的定義,其數據轉換鏈條大概為,
數據庫DB 》PO 》DTO 》VO
可以看到,在項目中不同的應用分層DB/DAO/Service/Manager/Web,經常會需要把一個數據對象轉換為其它類型的數據對象,轉換的同時復制部分對象屬性,有時部分屬性需要從多個數據對象獲取進行組裝。這些數據的轉換有一個共同的需求,那就是從一個源對象變為目標對象
源對象 Source s 》目標對象 Target t
接下來我們就需要討論這個轉換過程。
2. 單個對象的轉換
1)簡單的Java對象轉換,使用BeanUtils.copyProperties
使用Spring都知道Spring Beans中提供了一個BeanUtils,可以用于對象的屬性復制,其使用方法為,
Target t = new Target();
BeanUtils.copyProperties(s, t);
BeanUtils.copyProperties(s, t, 'password');
其中,第二個copyProperties方法中第三個參數是告知復制過程中忽略復制'password'這個屬性。
2)單個對象的轉換,指定目標類
BeanUtils.copyProperties不提供目標對象的創建,因此每次都需要new出一個目標對象。為了能夠省去這一步,可以使用下面的方法。
實現代碼
public static T convert(S s, Class clazz) {
T t = null;
try {
t = clazz.newInstance();
BeanUtils.copyProperties(s, t);
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
上述方法將對象的生成封裝起來返回。
使用樣例
Target t = convert(s, Target.class);
使用中直接指定目標類,代碼更加簡潔易懂。
3. List/Set集合之間的轉換
在很多時候,我們不僅處理一個對象的轉換,而是面對集合的對象,這時需要能夠對集合中的對象進行批量處理轉換。
1)List集合轉換,將列表中每一個實體轉換為目標類
實現代碼
public static List convert(Iterable iterable, Class clazz) {
return StreamSupport.stream(iterable.spliterator(), false)
.map(s -> convert(s, clazz))
.collect(Collectors.toList());
}
使用樣例
List targets = convert(srcCollection, Target.class);
2)List集合轉換,提供一個mapper轉換方法,將列表中每一個實體對象轉換為目標類
實現代碼
public static List convert(Iterable iterable,
Function super S, ? extends T> mapper) {
return StreamSupport.stream(iterable.spliterator(), false)
.map(mapper)
.collect(Collectors.toList());
}
使用樣例
List targets = convert(srcCollection, mapper);
其中mapper的定義為Function super S, ? extends T>,即該函數需要一個源對象作為輸入參數,返回一個目標對象
3)List集合轉換,轉換為指定的List/Set容器類,集合中的實體對象不變
實現代碼
public static > U collect(Iterable iterable, CollectionFactory factory) {
U collection = factory.createCollection();
iterable.forEach(collection::add);
return collection;
}
其中CollectionFactory為一個集合類工廠。
使用樣例
Iterable iterable = IntStream.range(0, 5).boxed().collect(Collectors.toList());
ArrayList arrayList = collect(iterable, ArrayList::new);
HashSet hashSet = collect(iterable, HashSet::new);
LinkedList linkedList = collect(iterable, LinkedList::new);
上述將一個Collection集合轉換為ArrayList/HashSet/LinkedList,集合中的整型變量對象保持不變。
4)List集合轉換,轉換為指定的List/Set容器類,并將集合中的實體對象轉換為目標類
實現代碼
public static , T> U collect(Iterable iterable, Class clazz, CollectionFactory factory) {
Iterable list = convert(iterable, clazz);
U collection = factory.createCollection();
list.forEach(collection::add);
return collection;
}
使用樣例
Iterable users = UserDao.SingleInstance.findAll();
ArrayList arrayList = collect(users, UserVO.class, ArrayList::new);
HashSet hashSet = collect(users, UserVO.class, HashSet::new);
LinkedList linkedList = collect(users, UserVO.class, LinkedList::new);
上述將一個Collection集合轉換為ArrayList/HashSet/LinkedList,同時集合中的UserEntity變量對象轉換為了UserVO。
4. List/Set/Map之間的轉換
Java中Map的處理效率比List/Set高效不少,有些時候需要在List/Set/Map之間進行轉換。
1)List集合轉換,轉換為Map集合,提供一個keyGenerator生成key,實體對象保存為value
實現代碼
public static Map map(Iterable iterable, Function super S, String> keyGenerator) {
return StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.toMap(keyGenerator, Function.identity()));
}
使用樣例
List users = UserDao.SingleInstance.findAll();
Map result = map(users, UserEntity::getName);
上述樣例中由UserEntity::getName來生成對象的鍵值,其必須為保證唯一。
2)Map集合轉換,轉換為List集合,實體對象保持不變
實現代碼
public static > U collect(Map map, CollectionFactory factory) {
U collection = factory.createCollection();
map.values().iterator().forEachRemaining(collection::add);
return collection;
}
使用樣例
Map users;
List list1 = collect(users, ArrayList::new);
Set set = collect(users, HashSet::new);
List list2 = collect(users, LinkedList::new);
Collection collection = users.values();
上述將一個用戶的Map集合轉換為List集合,可以看到一個簡單獲得List集合的方法就是使用map.values()方法。
3)Map集合轉換,轉換為指定的Map容器類
實現代碼
public static > U map(Map srcMap, Class clazz, MapFactory factory) {
U u = factory.createMap();
srcMap.entrySet()
.forEach(ksEntry -> u.put(ksEntry.getKey(),
convert(ksEntry.getValue(), clazz)));
return u;
}
使用樣例
Map users;
Map m1 = map(users, UserVO.class, HashMap::new);
Map m2 = map(users, UserVO.class, LinkedHashMap::new);
Hashtable m3 = map(users, UserVO.class, Hashtable::new);
上述將一個用戶的Map集合轉換為List集合,可以看到一個簡單獲得List集合的方法就是使用map.values()方法。
5. 源代碼
演示代碼倉庫地址:https://gitee.com/pphh/blog,可以通過如下git clone命令獲取倉庫代碼,
git clone git@gitee.com:pphh/blog.git
本篇博文的程序代碼樣例在文件路徑171201_java_object_copy\171201_java_object_copy_convert中,請使用JDK8及后續版本編譯并運行項目代碼。
6. 參考資料
POJO阿里巴巴Java開發手冊(2017版本):應用分層和領域模型PO/DTO/VO
總結
以上是生活随笔為你收集整理的java对象的类型转换_Java对象的类型转换和属性复制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql导入100000000需要多久
- 下一篇: java 反射 单列_轻松掌握Java单