Java中拷贝的概念
- 在Java语言中,拷贝一个对象时,有浅拷贝与深拷贝两种
名称 | 说明 |
---|---|
浅拷贝 | 只拷贝源对象的地址,所以新对象与老对象共用一个地址,当该地址变化时,两个对象也会随之改变。 |
深拷贝 | 拷贝对象的所有值,即使源对象发生任何改变,拷贝的值也不会变化。 |
一、常见的浅拷贝方式
- 对象浅拷贝 示例:
public class User {
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "name:" + this.name + ";" + "age:" + this.age + ";" + "sex:" + this.sex;
}
}
public class UserTest {
public static void main(String[] args) {
User u1 = new User();
u1.setName("张三");
u1.setAge(18);
u1.setSex("男");
User u2= u1;
System.out.println("u1==="+u1.getAge());
u1.setAge(20);
System.out.println("u2===="+u2.getAge());
}
}
image.png
- List浅拷贝 示例:
public class User {
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "name:" + this.name + ";" + "age:" + this.age + ";" + "sex:" + this.sex;
}
}
public class UserTest {
public class UserTest {
public static void main(String[] args) {
List<User> l1= new ArrayList<>();
User u1 = new User();
u1.setName("张三");
u1.setAge(18);
u1.setSex("男");
l1.add(u1);
User u2= new User();
u2.setName("李思");
u2.setAge(18);
u2.setSex("女");
l1.add(u2);
List<User> l2= new ArrayList<>(l1);
System.out.println("l1变前");
System.out.println("===l1===");
l1.forEach(System.out::println);
System.out.println("===l2===");
l1.forEach(System.out::println);
u1.setAge(20);
System.out.println("l1变后");
System.out.println("===l1===");
l1.forEach(System.out::println);
System.out.println("===l2===");
l1.forEach(System.out::println);
}
}
image.png
二、常见的深拷贝方式
-
实现步骤:
(1) 构造函数方式(new的方式) (2) 重写clone方法 (3) Apache Commons Lang序列化 (4) Gson序列化 (5) Jackson序列化 注意:构造函数方式是创建一个新的对象,然后通过源对象的get方法与新对象set方法,把源对象的值复制新对象,这里就不再操作。缺点:在拷贝的对象数量较少时,可以使用,但是对象数量过多时,会大大增加系统开销,开发中应避免使用。
1、重写clone方法
1>需要拷贝对象的类,去实现[Cloneable]接口
2>重写clone方法
3>使用"**对象.clone()**"的方式进行拷贝
- 示例
public class User implements Cloneable{
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "name:" + this.name + ";" + "age:" + this.age + ";" + "sex:" + this.sex;
}
@Override
protected User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
}
public class UserTest {
public static void main(String[] args) throws CloneNotSupportedException {
User u1 = new User();
u1.setName("张三");
u1.setAge(18);
u1.setSex("男");
User u2= u1.clone();
System.out.println("===u1变前===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
u1.setAge(20);
System.out.println("===u1变后===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
}
}
image.png
2、Apache Commons Lang序列化
1>导入Commons包
- 示例
public class User implements Serializable {
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "name:" + this.name + ";" + "age:" + this.age + ";" + "sex:" + this.sex;
}
}
public class UserTest {
public static void main(String[] args) throws CloneNotSupportedException {
User u1 = new User();
u1.setName("张三");
u1.setAge(18);
u1.setSex("男");
User u2= (User) SerializationUtils.clone(u1);
System.out.println("===u1变前===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
u1.setAge(20);
System.out.println("===u1变后===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
}
}
image.png
3、Gson序列化
1>导入Gson依赖
- 示例
public class User {
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "name:" + this.name + ";" + "age:" + this.age + ";" + "sex:" + this.sex;
}
}
public class UserTest {
public static void main(String[] args) throws CloneNotSupportedException {
User u1 = new User();
u1.setName("张三");
u1.setAge(18);
u1.setSex("男");
Gson gson =new Gson();
User u2= gson.fromJson(gson.toJson(u1), User.class);
System.out.println("===u1变前===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
u1.setAge(20);
System.out.println("===u1变后===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
}
}
image.png
4、Jackson序列化
1>导入Jackson依赖
- 示例
public class User {
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString(){
return "name:" + this.name + ";" + "age:" + this.age + ";" + "sex:" + this.sex;
}
}
public class UserTest {
public static void main(String[] args) throws CloneNotSupportedException {
User u1 = new User();
u1.setName("张三");
u1.setAge(18);
u1.setSex("男");
User u2 = null;
ObjectMapper mapper = new ObjectMapper() ;
try {
u2 = mapper.readValue(mapper.writevalueAsString(u1), User.class);
}catch (IOException e) {
e.printstackTrace();
}
System.out.println("===u1变前===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
u1.setAge(20);
System.out.println("===u1变后===");
System.out.println("u1==="+u1);
System.out.println("u2==="+u2);
}
}
image.png
四、总结
image.png