深拷贝和浅拷贝
例程
package com.testng.demo.model;
import lombok.Data;
@Data
public class Role {
String name;
}
package com.testng.demo.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel
public class User {
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value="年龄")
private int age;
@ApiModelProperty(value= "id")
private String id;
@ApiModelProperty(value = "密码")
private String password;
***private Role role;***
public User(String id, Role role) {
this.id = id;
this.role = role;
}
public User(){
}
}
什么是引用拷贝
public class CopyTest {
public static void main(String[] args) {
Role admin = new Role("admin");
User user = new User("001", admin);
User user1=user;
System.out.println("user地址:"+user+"\nuser1地址:"+user1);
System.out.println(user1==user);
}
}
输出:
user地址:com.testng.demo.model.User@7f9a81e8
user1地址:com.testng.demo.model.User@7f9a81e8
true
浅拷贝
User类实现了implements Cloneable接口,覆盖(重写override)了Object类的clone方法
package com.testng.demo.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
public class User implements Cloneable {
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value="年龄")
private int age;
@ApiModelProperty(value= "id")
private String id;
@ApiModelProperty(value = "密码")
private String password;
public User(String id, Role role) {
this.id = id;
this.role = role;
}
public User(){
}
private Role role;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public User clone(){
try {
User clone = (User) super.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
package com.testng.demo.test;
import com.testng.demo.model.Role;
import com.testng.demo.model.User;
public class CopyTest {
public static void main(String[] args) {
Role admin = new Role("admin");
User user = new User("001", admin);
//引用拷贝
User user1=user;
System.out.println("user地址:"+user+"\nuser1地址:"+user1);
System.out.println(user1==user);
**//浅拷贝,没拷贝User的引用类型的成员变量role
User clone = user.clone();
System.out.println("user地址:"+user+"\nclone地址:"+clone);
System.out.println(clone==user);
System.out.println("user的role地址:"+user.getRole()+"\nclone的role地址:"+clone.getRole());
System.out.println(user.getRole()==clone.getRole());**
}
}
输出:
com.testng.demo.test.CopyTest
user地址:com.testng.demo.model.User@7f9a81e8
user1地址:com.testng.demo.model.User@7f9a81e8
true
***user地址:com.testng.demo.model.User@7f9a81e8
clone地址:com.testng.demo.model.User@9629756
false
user的role地址:com.testng.demo.model.Role@62ee68d8
clone的role地址:com.testng.demo.model.Role@62ee68d8
true***
Process finished with exit code 0
深拷贝
User的引用类型的成员变量Role类也需要实现Cloneable接口,覆盖clone方法,之后在User类里的clone方法中会对Role变量进行clone, clone方法本质是在堆中创建一个新的对象。
package com.testng.demo.model;
import lombok.Data;
public class Role implements Cloneable{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role(String name) {
this.name = name;
}
public Role() {
}
public Role clone(){
try {
Role clone = (Role) super.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
public User clone(){
try {
User clone = (User) super.clone();
//引用类型的成员变量role也进行了clone
***clone.setRole(role.clone());***
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
//注意这段测试代码没改
package com.testng.demo.test;
import com.testng.demo.model.Role;
import com.testng.demo.model.User;
public class CopyTest {
public static void main(String[] args) {
Role admin = new Role("admin");
User user = new User("001", admin);
//引用拷贝
User user1=user;
System.out.println("user地址:"+user+"\nuser1地址:"+user1);
System.out.println(user1==user);
//深拷贝,User的引用类型的成员变量role也在上面的例程中进行了拷贝
User clone = user.clone();
System.out.println("user地址:"+user+"\nclone地址:"+clone);
System.out.println(clone==user);
System.out.println("user的role地址:"+user.getRole()+"\nclone的role地址:"+clone.getRole());
System.out.println(user.getRole()==clone.getRole());
}
}
输出:
/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=52077:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/chensiyue/Learning/TestDemo/SpringDemo/target/classes:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-starter-web/2.1.6.RELEASE/spring-boot-starter-web-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-starter/2.1.6.RELEASE/spring-boot-starter-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot/2.1.6.RELEASE/spring-boot-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-starter-logging/2.1.6.RELEASE/spring-boot-starter-logging-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/apache/logging/log4j/log4j-to-slf4j/2.11.2/log4j-to-slf4j-2.11.2.jar:/Users/chensiyue/Learning/maven_repo/org/apache/logging/log4j/log4j-api/2.11.2/log4j-api-2.11.2.jar:/Users/chensiyue/Learning/maven_repo/org/slf4j/jul-to-slf4j/1.7.26/jul-to-slf4j-1.7.26.jar:/Users/chensiyue/Learning/maven_repo/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-core/5.1.8.RELEASE/spring-core-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-jcl/5.1.8.RELEASE/spring-jcl-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/yaml/snakeyaml/1.23/snakeyaml-1.23.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-starter-json/2.1.6.RELEASE/spring-boot-starter-json-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/jackson/core/jackson-databind/2.9.9/jackson-databind-2.9.9.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.9.9/jackson-datatype-jdk8-2.9.9.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.9.9/jackson-datatype-jsr310-2.9.9.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.9/jackson-module-parameter-names-2.9.9.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-starter-tomcat/2.1.6.RELEASE/spring-boot-starter-tomcat-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/apache/tomcat/embed/tomcat-embed-core/9.0.21/tomcat-embed-core-9.0.21.jar:/Users/chensiyue/Learning/maven_repo/org/apache/tomcat/embed/tomcat-embed-el/9.0.21/tomcat-embed-el-9.0.21.jar:/Users/chensiyue/Learning/maven_repo/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.21/tomcat-embed-websocket-9.0.21.jar:/Users/chensiyue/Learning/maven_repo/org/hibernate/validator/hibernate-validator/6.0.17.Final/hibernate-validator-6.0.17.Final.jar:/Users/chensiyue/Learning/maven_repo/javax/validation/validation-api/2.0.1.Final/validation-api-2.0.1.Final.jar:/Users/chensiyue/Learning/maven_repo/org/jboss/logging/jboss-logging/3.3.2.Final/jboss-logging-3.3.2.Final.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-web/5.1.8.RELEASE/spring-web-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-beans/5.1.8.RELEASE/spring-beans-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-webmvc/5.1.8.RELEASE/spring-webmvc-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-aop/5.1.8.RELEASE/spring-aop-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-context/5.1.8.RELEASE/spring-context-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-expression/5.1.8.RELEASE/spring-expression-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/Users/chensiyue/Learning/maven_repo/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/chensiyue/Learning/maven_repo/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-swagger2/2.9.2/springfox-swagger2-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/io/swagger/swagger-annotations/1.5.20/swagger-annotations-1.5.20.jar:/Users/chensiyue/Learning/maven_repo/io/swagger/swagger-models/1.5.20/swagger-models-1.5.20.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-spi/2.9.2/springfox-spi-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-core/2.9.2/springfox-core-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/net/bytebuddy/byte-buddy/1.9.13/byte-buddy-1.9.13.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-schema/2.9.2/springfox-schema-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-swagger-common/2.9.2/springfox-swagger-common-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-spring-web/2.9.2/springfox-spring-web-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/com/google/guava/guava/20.0/guava-20.0.jar:/Users/chensiyue/Learning/maven_repo/com/fasterxml/classmate/1.4.0/classmate-1.4.0.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/plugin/spring-plugin-core/1.2.0.RELEASE/spring-plugin-core-1.2.0.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/plugin/spring-plugin-metadata/1.2.0.RELEASE/spring-plugin-metadata-1.2.0.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/mapstruct/mapstruct/1.2.0.Final/mapstruct-1.2.0.Final.jar:/Users/chensiyue/Learning/maven_repo/io/springfox/springfox-swagger-ui/2.9.2/springfox-swagger-ui-2.9.2.jar:/Users/chensiyue/Learning/maven_repo/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar:/Users/chensiyue/Learning/maven_repo/com/alibaba/druid-spring-boot-starter/1.1.17/druid-spring-boot-starter-1.1.17.jar:/Users/chensiyue/Learning/maven_repo/com/alibaba/druid/1.1.17/druid-1.1.17.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-autoconfigure/2.1.6.RELEASE/spring-boot-autoconfigure-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/mybatis/spring/boot/mybatis-spring-boot-starter/2.1.0/mybatis-spring-boot-starter-2.1.0.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/boot/spring-boot-starter-jdbc/2.1.6.RELEASE/spring-boot-starter-jdbc-2.1.6.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/com/zaxxer/HikariCP/3.2.0/HikariCP-3.2.0.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-jdbc/5.1.8.RELEASE/spring-jdbc-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/springframework/spring-tx/5.1.8.RELEASE/spring-tx-5.1.8.RELEASE.jar:/Users/chensiyue/Learning/maven_repo/org/mybatis/spring/boot/mybatis-spring-boot-autoconfigure/2.1.0/mybatis-spring-boot-autoconfigure-2.1.0.jar:/Users/chensiyue/Learning/maven_repo/org/mybatis/mybatis/3.5.2/mybatis-3.5.2.jar:/Users/chensiyue/Learning/maven_repo/org/mybatis/mybatis-spring/2.0.2/mybatis-spring-2.0.2.jar:/Users/chensiyue/Learning/maven_repo/com/alibaba/fastjson/1.2.4/fastjson-1.2.4.jar com.testng.demo.test.CopyTest
user地址:com.testng.demo.model.User@7f9a81e8
user1地址:com.testng.demo.model.User@7f9a81e8
true
***user地址:com.testng.demo.model.User@7f9a81e8
clone地址:com.testng.demo.model.User@9629756
false
user的role地址:com.testng.demo.model.Role@62ee68d8
clone的role地址:com.testng.demo.model.Role@735b5592
false***
·
Process finished with exit code 0