透过字节码实现deep clone
原理就是按照ObjectInputStream 和ObjectOutputStream 对一个对象进行序列话和反序列话的原理和过程。
public static <T extends Serializable> T clone(T object) {
if (object == null) {
return null;
}
byte[] objectData = serialize(object);
ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
ClassLoaderAwareObjectInputStream in = null;
try {
// stream closed in the finally
in = new ClassLoaderAwareObjectInputStream(bais, object.getClass().getClassLoader());
/*
* when we serialize and deserialize an object,
* it is reasonable to assume the deserialized object
* is of the same type as the original serialized object
*/
@SuppressWarnings("unchecked") // see above
T readObject = (T) in.readObject();
return readObject;
} catch (ClassNotFoundException ex) {
throw new SerializationException("ClassNotFoundException while reading cloned object data", ex);
} catch (IOException ex) {
throw new SerializationException("IOException while reading cloned object data", ex);
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
throw new SerializationException("IOException on closing cloned object data InputStream.", ex);
}
}
}
static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
private ClassLoader classLoader;
/**
* Constructor.
* @param in The <code>InputStream</code>.
* @param classLoader classloader to use
* @throws IOException if an I/O error occurs while reading stream header.
* @see java.io.ObjectInputStream
*/
public ClassLoaderAwareObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException {
super(in);
this.classLoader = classLoader;
}
/**
* Overriden version that uses the parametrized <code>ClassLoader</code> or the <code>ClassLoader</code>
* of the current <code>Thread</code> to resolve the class.
* @param desc An instance of class <code>ObjectStreamClass</code>.
* @return A <code>Class</code> object corresponding to <code>desc</code>.
* @throws IOException Any of the usual Input/Output exceptions.
* @throws ClassNotFoundException If class of a serialized object cannot be found.
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
String name = desc.getName();
try {
return Class.forName(name, false, classLoader);
} catch (ClassNotFoundException ex) {
return Class.forName(name, false, Thread.currentThread().getContextClassLoader());
}
}
}