improve DeepCopy util class

This commit is contained in:
Sebastian Sdorra
2017-01-15 13:13:59 +01:00
parent 3536c29908
commit 1591ab43b3
2 changed files with 47 additions and 200 deletions

View File

@@ -56,57 +56,41 @@ import java.io.ObjectOutputStream;
* @since 1.29
* @see <a href="http://javatechniques.com/blog/faster-deep-copies-of-java-objects" target="_blank">http://javatechniques.com/blog/faster-deep-copies-of-java-objects</a>
*/
public final class DeepCopy
{
public final class DeepCopy {
private DeepCopy() {
}
/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*
* @param orig
* @param <T>
* @param orig object to copy
* @param <T> type of object to copy
*
* @return
* @return deep copy of object
*
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static <T> T copy(T orig) throws IOException
{
T obj = null;
Closer closer = Closer.create();
try
{
public static <T> T copy(T orig) throws IOException {
try (Closer closer = Closer.create()) {
// Write the object out to a byte array
FastByteArrayOutputStream fbos =
closer.register(new FastByteArrayOutputStream());
ObjectOutputStream out = closer.register(new ObjectOutputStream(fbos));
out.writeObject(orig);
out.flush();
out.close();
FastByteArrayOutputStream fbos = closer.register(new FastByteArrayOutputStream());
try (ObjectOutputStream out = new ObjectOutputStream(fbos)) {
out.writeObject(orig);
out.flush();
}
// Retrieve an input stream from the byte array and read
// a copy of the object back in.
// use ScmObjectInputStream to solve ClassNotFoundException
// for plugin classes
ObjectInputStream in =
closer.register(new ScmObjectInputStream(fbos.getInputStream()));
obj = (T) in.readObject();
}
catch (Exception ex)
{
ObjectInputStream in = closer.register(new ScmObjectInputStream(fbos.getInputStream()));
return (T) in.readObject();
} catch (ClassNotFoundException ex) {
throw new IOException("could not copy object", ex);
}
finally
{
closer.close();
}
return obj;
}
}

View File

@@ -45,23 +45,20 @@ import java.io.IOException;
import java.io.Serializable;
/**
*
* Unit tests for {@link DeepCopy}.
*
* @author Sebastian Sdorra
*/
public class DeepCopyTest
{
public class DeepCopyTest {
/**
* Method description
*
* Tests {@link DeepCopy#copy(Object)}.
*
* @throws IOException
*/
@Test
public void testDeepCopy() throws IOException
{
Person orig = new Person("Tricia", "McMillan",
new Address("Magrathea", "Mainstreet 3"));
public void testDeepCopy() throws IOException {
Person orig = new Person("Tricia", "McMillan", new Address("Magrathea", "Mainstreet 3"));
Person copy = DeepCopy.copy(orig);
assertNotSame(orig, copy);
@@ -69,73 +66,35 @@ public class DeepCopyTest
}
/**
* Method description
*
* Tests {@link DeepCopy#copy(Object)} with a non serializable object.
*
* @throws IOException
*/
@Test(expected = IOException.class)
public void testDeepCopyNonSerializable() throws IOException
{
public void testDeepCopyNonSerializable() throws IOException {
DeepCopy.copy(new NonSerializable());
}
//~--- inner classes --------------------------------------------------------
/**
* Class description
*
*
* @version Enter version here..., 14/03/08
* @author Enter your name here...
*/
private static class Address implements Serializable
{
private static class Address implements Serializable {
/** Field description */
private static final long serialVersionUID = 3200816222378286310L;
//~--- constructors -------------------------------------------------------
/**
* Constructs ...
*
*/
public Address() {}
/**
* Constructs ...
*
*
* @param city
* @param street
*/
public Address(String city, String street)
{
public Address(String city, String street) {
this.city = city;
this.street = street;
}
//~--- methods ------------------------------------------------------------
/**
* Method description
*
*
* @param obj
*
* @return
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass())
{
if (getClass() != obj.getClass()) {
return false;
}
@@ -144,94 +103,40 @@ public class DeepCopyTest
return Objects.equal(city, other.city)
&& Objects.equal(street, other.street);
}
/**
* Method description
*
*
* @return
*/
@Override
public int hashCode()
{
public int hashCode() {
return Objects.hashCode(city, street);
}
//~--- get methods --------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public String getCity()
{
public String getCity() {
return city;
}
/**
* Method description
*
*
* @return
*/
public String getStreet()
{
public String getStreet() {
return street;
}
//~--- fields -------------------------------------------------------------
/** Field description */
private String city;
/** Field description */
private String street;
}
/**
* Class description
*
*
* @version Enter version here..., 14/03/08
* @author Enter your name here...
*/
private static class NonSerializable {}
private static class Person implements Serializable {
/**
* Class description
*
*
* @version Enter version here..., 14/03/08
* @author Enter your name here...
*/
private static class Person implements Serializable
{
/** Field description */
private static final long serialVersionUID = -2098386757802626539L;
//~--- constructors -------------------------------------------------------
/**
* Constructs ...
*
*/
public Person() {}
/**
* Constructs ...
*
*
* @param firstname
* @param lastname
* @param address
*/
public Person(String firstname, String lastname, Address address)
{
public Person(String firstname, String lastname, Address address) {
this.firstname = firstname;
this.lastname = lastname;
this.address = address;
@@ -239,24 +144,13 @@ public class DeepCopyTest
//~--- methods ------------------------------------------------------------
/**
* Method description
*
*
* @param obj
*
* @return
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass())
{
if (getClass() != obj.getClass()) {
return false;
}
@@ -267,62 +161,31 @@ public class DeepCopyTest
&& Objects.equal(address, other.address);
}
/**
* Method description
*
*
* @return
*/
@Override
public int hashCode()
{
public int hashCode() {
return Objects.hashCode(firstname, lastname, address);
}
//~--- get methods --------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public Address getAddress()
{
public Address getAddress() {
return address;
}
/**
* Method description
*
*
* @return
*/
public String getFirstname()
{
public String getFirstname() {
return firstname;
}
/**
* Method description
*
*
* @return
*/
public String getLastname()
{
public String getLastname() {
return lastname;
}
//~--- fields -------------------------------------------------------------
/** Field description */
private Address address;
/** Field description */
private String firstname;
/** Field description */
private String lastname;
}
}