Add complete codes for an article about deep copy (#3610)
* Add complete codes for an article about deep copy * Add missing gson dependency * Apply changes suggested in PR comments * Apply changes suggested in PR comments * Apply changes suggested in PR comments
This commit is contained in:
parent
378cae0821
commit
327719e1bb
|
@ -78,6 +78,11 @@
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>${jackson.version}</version>
|
<version>${jackson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>${gson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -468,6 +473,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<!-- marshalling -->
|
<!-- marshalling -->
|
||||||
<jackson.version>2.8.5</jackson.version>
|
<jackson.version>2.8.5</jackson.version>
|
||||||
|
<gson.version>2.8.2</gson.version>
|
||||||
|
|
||||||
<!-- logging -->
|
<!-- logging -->
|
||||||
<org.slf4j.version>1.7.21</org.slf4j.version>
|
<org.slf4j.version>1.7.21</org.slf4j.version>
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Address implements Serializable, Cloneable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
try {
|
||||||
|
return (Address) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
return new Address(this.street, this.getCity(), this.getCountry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1740913841244949416L;
|
||||||
|
private String street;
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
public Address(Address that) {
|
||||||
|
this(that.getStreet(), that.getCity(), that.getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String street, String city, String country) {
|
||||||
|
this.street = street;
|
||||||
|
this.city = city;
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class User implements Serializable, Cloneable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -3427002229954777557L;
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
private Address address;
|
||||||
|
|
||||||
|
public User(String firstName, String lastName, Address address) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(User that) {
|
||||||
|
this(that.getFirstName(), that.getLastName(), new Address(that.getAddress()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
User user;
|
||||||
|
try {
|
||||||
|
user = (User) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
user = new User(this.getFirstName(), this.getLastName(), this.getAddress());
|
||||||
|
}
|
||||||
|
user.address = (Address) this.address.clone();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.SerializationUtils;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
public class DeepCopyUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreatingDeepCopyWithCopyConstructor_thenObjectsShouldNotBeSame() {
|
||||||
|
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
|
||||||
|
User deepCopy = new User(pm);
|
||||||
|
|
||||||
|
assertThat(deepCopy).isNotSameAs(pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenConstructorCopyShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User deepCopy = new User(pm);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenCloneCopyShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User deepCopy = (User) pm.clone();
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenCommonsCloneShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User deepCopy = (User) SerializationUtils.clone(pm);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenGsonCloneShouldNotChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
Gson gson = new Gson();
|
||||||
|
User deepCopy = gson.fromJson(gson.toJson(pm), User.class);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenJacksonCopyShouldNotChange() throws IOException {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
User deepCopy = objectMapper.readValue(objectMapper.writeValueAsString(pm), User.class);
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(deepCopy.getAddress().getCountry()).isNotEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void whenMakingCopies_thenShowHowLongEachMethodTakes() throws CloneNotSupportedException, IOException {
|
||||||
|
int times = 1000000;
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = (User) SerializationUtils.clone(pm);
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Apache Commons Lang took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
Gson gson = new Gson();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = gson.fromJson(gson.toJson(pm), User.class);
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Gson took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = new User(pm);
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with the copy constructor took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = (User) pm.clone();
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Cloneable interface took " + (end - start) + " milliseconds.");
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
User primeMinisterClone = objectMapper.readValue(objectMapper.writeValueAsString(pm), User.class);
|
||||||
|
}
|
||||||
|
end = System.currentTimeMillis();
|
||||||
|
System.out.println("Cloning with Jackson took " + (end - start) + " milliseconds.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.deepcopy;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ShallowCopyUnitTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenShallowCopying_thenObjectsShouldNotBeSame() {
|
||||||
|
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
|
||||||
|
User shallowCopy = new User(pm.getFirstName(), pm.getLastName(), pm.getAddress());
|
||||||
|
|
||||||
|
assertThat(shallowCopy)
|
||||||
|
.isNotSameAs(pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenModifyingOriginalObject_thenCopyShouldChange() {
|
||||||
|
Address address = new Address("Downing St 10", "London", "England");
|
||||||
|
User pm = new User("Prime", "Minister", address);
|
||||||
|
User shallowCopy = new User(pm.getFirstName(), pm.getLastName(), pm.getAddress());
|
||||||
|
|
||||||
|
address.setCountry("Great Britain");
|
||||||
|
|
||||||
|
assertThat(shallowCopy.getAddress().getCountry())
|
||||||
|
.isEqualTo(pm.getAddress().getCountry());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue