知识点1(java有9种传递函数参数时是传值):
8大基础数据类型加String:
1,字节 byte
2,短整型 short
3,整型int
4,长整形 long
5,字符型 char
6,浮点型 float
7,双精度型 double
8,布尔型 boolean
9,String
这8大基础类型+String是传值。
知识点2.BeanUtils.copyProperties(entity, userDto)
1.从entity拷贝数据到userDto中。
2.是浅拷贝。
3.使用的是反射调用set和get方法设置值,要有相同属性名字。
知识点3(深度克隆对象的三个方法):
方法1. // 重写clone方法
import java.util.ArrayList;
/**
* 1.必须实现Cloneable接口.
* 2.写clone方法的话,在clone中代码上每一处都要实现深复制.
* @author jianan
*/
class Work implements Cloneable{
private String strText;
private ArrayList<String> array = new ArrayList<String>();
@SuppressWarnings("unchecked")
@Override
protected Work clone(){
Work work;
try {
work = (Work)super.clone();
work.strText = this.strText;
work.array = (ArrayList<String>) (this.array.clone()); //深克隆
return work;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public void addImage(String imgName){
array.add(imgName);
}
public void setText(String strText){
this.strText = strText;
}
public void display(String str){
System.out.println(str);
System.out.println("Text:" + strText);
for(int i = 0; i < array.size(); i++){
System.out.println("Image:" + array.get(i));
}
System.out.println();
}
}
//测试函数
public class Main {
public static void main(String[] args) {
Work work = new Work();
work.setText("111");
work.addImage("1.png");
work.addImage("2.png");
work.addImage("3.png");
work.display("111");
Work work2 = work.clone();
work2.setText("2");
work2.addImage("4.png");
work2.addImage("5.png");
work2.addImage("6.png");
work2.display("222");
work.display("111");
}
}
方法2. // io读写序列化反序列化
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
/**
* 1.实现Serializable接口即可.toString方法不用重写因为该接口里面本身就为空.
* @author jianan
*/
//深克隆 工具
class DepthCloneUtil{
public static Object depthClone(Object srcObj){
Object cloneObj = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(out);
oo.writeObject(srcObj);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream oi = new ObjectInputStream(in);
cloneObj = oi.readObject();
} catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
return cloneObj;
}
}
//
class Work implements Serializable{
private static final long serialVersionUID = -3219618174845671783L; //会自动补充的
private String strText;
private ArrayList<String> array = new ArrayList<String>();
public void addImage(String imgName){
array.add(imgName);
}
public void setText(String strText){
this.strText = strText;
}
public void display(String str){
System.out.println(str);
System.out.println("Text:" + strText);
for(int i = 0; i < array.size(); i++){
System.out.println("Image:" + array.get(i));
}
System.out.println();
}
}
//测试函数
public class Main {
public static void main(String[] args) {
Work work = new Work();
work.setText("111");
work.addImage("1.png");
work.addImage("2.png");
work.addImage("3.png");
work.display("111");
Work work2 = (Work)DepthCloneUtil.depthClone(work); //如果采用对象序列化的话,
work2.setText("2");
work2.addImage("4.png");
work2.addImage("5.png");
work2.addImage("6.png");
work2.display("222");
work.display("111");
}
}
直接写一个clone方法。
2种方式都实现了深度克隆,输出结果都是:
/*
111
Text:111
Image:1.png
Image:2.png
Image:3.png
222
Text:2
Image:1.png
Image:2.png
Image:3.png
Image:4.png
Image:5.png
Image:6.png
111
Text:111
Image:1.png
Image:2.png
Image:3.png
*/
方法3:使用orika(推荐!!!)
实体必须有无参构造!!!
pom.xml
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.4.6</version>
</dependency>
例子1---代替BeanUtils.copyProperties使用
OrikaUtil.java
package org.example.testOrika;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.impl.DefaultMapperFactory;
public class OrikaUtil {
public static MapperFacade MAPPER_FACADE = new DefaultMapperFactory.Builder().build().getMapperFacade();
}
Book.java
package org.example.testOrika;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private String id;
}
User.java
package org.example.testOrika;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString
public class User {
private String id;
private String name;
private List<Book> books;
}
UserVo.java
package org.example.testOrika;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString
public class UserVo {
private String id;
private String name;
private List<Book> books;
}
Main.java
package org.example.testOrika;
import com.google.common.collect.Lists;
/*
必须含有无参构造
*/
public class Main {
public static void main(String[] args) {
// 原对象
User a = new User();
a.setId("123");
a.setName("1231");
a.setBooks(Lists.newArrayList(Book.builder().id("1").build()));
// 使用orika复制工具将A复制到B对象中(深拷贝)
UserVo map = OrikaUtil.MAPPER_FACADE.map(a, UserVo.class);
System.out.println(map);
}
}
/*
UserVo(id=123, name=1231, books=[Book(id=1)])
*/
----------例子2.深度克隆
OrikaUtils.java
package org.example.testOrika.utils;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.impl.DefaultMapperFactory;
public class OrikaUtils {
public static ThreadLocal<MapperFacade> facade = ThreadLocal.withInitial(() -> new DefaultMapperFactory.Builder().build().getMapperFacade());
}
Book.java
package org.example.testOrika.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor // 这个无参的必须有
@AllArgsConstructor
public class Book {
private String id;
@Override
public Book clone() {
Book clone = new Book();
clone.id = id;
return clone;
}
}
User.java
package org.example.testOrika.model;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.List;
@Data
@ToString
@NoArgsConstructor
public class User {
public String id;
public String name;
public List<Book> books = Lists.newArrayList();
@Override
public User clone() {
User clone = new User();
clone.id = id;
clone.name = name;
// 暂时book不拷贝
books.forEach(book -> {
clone.books.add(book.clone());
});
return clone;
}
}
Main.java
package org.example.testOrika;
import com.google.common.collect.Lists;
import org.example.testOrika.model.Book;
import org.example.testOrika.model.User;
import org.example.testOrika.utils.OrikaUtils;
/*
必须含有无参构造
*/
public class Main {
public static void main(String[] args) {
// 原对象
User user = new User();
user.setId("123");
user.setName("1231");
user.setBooks(Lists.newArrayList(new Book("1"), new Book("2"), new Book("3")));
// 使用orika复制工具将A复制到B对象中(深拷贝)
User orikaCloneUser = OrikaUtils.facade.get().map(user, User.class);
System.out.println(orikaCloneUser);
// 使用普通的做法深拷贝每一项
User cloneUser = user.clone();
System.out.println(cloneUser);
System.out.println();
}
}
可以看出:Orika最简单,也是深度克隆
/* 1亿次 75360 4451 */ 调用1亿次的话,可以看出Orika性能略低,不到原生的1/10
用arthas查看生成的类:
// sc模糊搜索类
[arthas@35972]$ sc *User*
com.taobao.arthas.core.util.UserStatUtil
com.taobao.arthas.core.util.UserStatUtil$1
ma.glasnost.orika.generated.Orika_User_User_Mapper2058567866428400$0
org.example.test.testOrika.User
Affect(row-cnt:4) cost in 33 ms.
// jad查看类的代码
[arthas@35972]$ jad ma.glasnost.orika.generated.Orika_User_User_Mapper2058567866428400$0
ClassLoader:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@7e93dc47
Location:
/C:/Users/elex/.m2/repository/ma/glasnost/orika/orika-core/1.4.6/orika-core-1.4.6.jar
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* org.example.test.testOrika.User
*/
package ma.glasnost.orika.generated;
import java.util.ArrayList;
import java.util.List;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.impl.GeneratedMapperBase;
import org.example.test.testOrika.User;
public class Orika_User_User_Mapper2058567866428400$0
extends GeneratedMapperBase {
@Override
public void mapBtoA(Object object, Object object2, MappingContext mappingContext) {
super.mapBtoA(object, object2, mappingContext);
User user = (User)object;
User user2 = (User)object2;
if (user.getBooks() != null) {
List list = new ArrayList(user.getBooks().size());
list.addAll(this.mapperFacade.mapAsList(user.getBooks(), this.usedTypes[0], this.usedTypes[0], mappingContext));
user2.setBooks(list);
} else if (user2.getBooks() != null) {
user2.setBooks(null);
}
user2.setId(user.getId());
user2.setName(user.getName());
if (this.customMapper != null) {
this.customMapper.mapBtoA(user, user2, mappingContext);
}
}
@Override
public void mapAtoB(Object object, Object object2, MappingContext mappingContext) {
super.mapAtoB(object, object2, mappingContext);
User user = (User)object;
User user2 = (User)object2;
if (user.getBooks() != null) {
List list = new ArrayList(user.getBooks().size());
list.addAll(this.mapperFacade.mapAsList(user.getBooks(), this.usedTypes[0], this.usedTypes[0], mappingContext));
user2.setBooks(list);
} else if (user2.getBooks() != null) {
user2.setBooks(null);
}
user2.setId(user.getId());
user2.setName(user.getName());
if (this.customMapper != null) {
this.customMapper.mapAtoB(user, user2, mappingContext);
}
}
}
------------同时orika可以避免并发访问错误,是线程安全的
SO_PlayerTroop.java
package com.example.demo.entity;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@Data
public class SO_PlayerTroop {
private Map<Integer, Hero> heroMap = new HashMap<>();
public void testWrite() {
for (int i = 0; i < 10000; i++) {
if (i % 2 == 0) {
if(heroMap.containsKey(i)){
Hero hero = heroMap.get(i);
hero.add();
}else {
Hero hero = new Hero();
heroMap.put(i, hero);
hero.add();
}
}else {
heroMap.remove(i);
}
}
}
public void testRead() {
for (Map.Entry<Integer, Hero> entry : heroMap.entrySet()) {
for (Integer num : entry.getValue().getNums()) {
System.out.println(num);
}
}
}
}
Hero.java
package com.example.demo.entity;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class Hero {
private List<Integer> nums = new ArrayList<>();
public Hero() {
nums.add(1);
nums.add(2);
}
public void add() {
for (int i = 0; i < nums.size(); i++) {
nums.set(i, nums.get(i) + 1);
}
}
}
Main.java
package com.example.demo;
import com.example.demo.entity.SO_PlayerTroop;
import com.example.demo.utils.OrikaUtils;
//@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// SpringApplication.run(DemoApplication.class, args);
SO_PlayerTroop so_playerTroop = new SO_PlayerTroop();
new Thread(() -> {
while (true) {
so_playerTroop.testWrite();
}
}).start();
new Thread(() -> {
while (true) {
// 深拷贝是不会有问题的
SO_PlayerTroop so_playerTroopCopy = OrikaUtils.deepClone(so_playerTroop, SO_PlayerTroop.class);
so_playerTroopCopy.testRead();
// 报并发修改错误
// so_playerTroop.testRead();
}
}).start();
System.out.println("start");
}
}
OrikaUtils.java // 线程安全的深度克隆
package com.example.demo.utils;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.impl.DefaultMapperFactory;
public class OrikaUtils {
private static final MapperFacade MAPPER_FACADE = new DefaultMapperFactory.Builder().build().getMapperFacade();
public static <S, D> D deepClone(S data, Class<D> clazz) {
return MAPPER_FACADE.map(data, clazz);
}
}
坑:
必须有无参构造。
字段不能是final,因为先调用无参构造,再进行set时就不成功!
------------------------------------
坑:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
代码
package com.example.testsb.testOrika;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.SerializationUtils;
@Slf4j
public class Main {
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
SO_Player so_player = new SO_Player("xx");
so_player.addBook(i);
SO_Player so_playerCopy = SerializationUtils.clone(so_player);
// log.info("so_playerCopy={}", so_playerCopy);
}
log.info("costTime={}", System.currentTimeMillis() - start);
}
}
实现序列化接口
package com.example.testsb.testOrika;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public class SO_Player implements Serializable {
private List<Book> bookList = new ArrayList<>();
private String name;
public SO_Player(String name) {
this.name = name;
}
public void addBook(int id) {
bookList.add(new Book(id));
}
}