参考JavaCodeGeeks上个这篇文章 http://www.javacodegeeks.com/2011/12/cloning-of-serializable-and-non.html 作者Craig Flichel

通常开发者都会依赖于第三方的类库来进行开发,这样避免重复制造轮子。特别是在Java的世界中,有着像Apache和Spring这样流行的开源项目。但在实际使用过程,我们总是无法控制这些类的行为,或者是只能控制一点点,叫人不爽。

这有时会带来问题。举个例子,比如说你要深度克隆一个没有提供合适克隆方法的对象,你准备咋整?

通过序列化来克隆

最简单的方法,如果对象实现了Serializable接口,那么直接利用这个就好。Apache Commons库中提供了一个方法去做这个,但为了完整,自己实现的话,代码可能就像下面这样:

public static Serializable cloneThroughSerialize(Serializable ser) throws Exception {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    serializeToOutputStream(ser, bos);
    byte[] bytes = bos.toByteArray();
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
            bytes));
    return (Serializable) ois.readObject();
}

private static void serializeToOutputStream(Serializable ser,
        OutputStream os) throws IOException {
    ObjectOutputStream oos = null;
    try {
        oos = new ObjectOutputStream(os);
        oos.writeObject(ser);
        oos.flush();
    } finally {
        oos.close();
    }
}

// using our custom method
Serializable cloned = cloneThroughSerialize(someObject);

// or with Apache Commons
Object cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);


但是,如果对象是非序列化的并且无法修改源代码呢?亦或者我们不能使对象实现Serializable接口呢?

方法一 ——Java深度克隆类库

有个非常小巧又nice的Java深度克隆类库,叫做cloning。它使用了Java出色的反射机制来提供Java对象的深度克隆,它几乎能深度克隆所有的Java对象。

Cloner cloner = new Cloner();
Object cloned = cloned.deepClone(someObject);

注意:该代码要运行起来,除了需要cloning包以外,还需要依赖objenesis包。

看见了吧,它非常简单高效,只需要非常少的代码就可完成Java对象的深度克隆。cloning还有其他非常棒的功能和示例,你可以在这里查看。

方法二 ——JSON克隆

如果不能引入任何新的第三方类库到我们的应用中呢?有些人可能想自己写一个,但是为了这个小case,写一个又不值得。

OK,只要我们能有方法来序列化和存储对象,我们就能够深度克隆对象。目前JSON使用最广泛,是一个不错的选择。

绝大多数Java中的JSON类库都提供了高效的方法来序列化任何POJO对象,无需要任何配置或者映射。这意味着,如果你的应用中包含了任何一个JSON类库,那么无需引入更多的第三方类库就可以实现深度克隆,你可以使用JSON类库来实现相同的功能。

注意:该方法会比其他的方法慢。但是对于绝大多数的应用来说,它不会引起任何性能问题。

下面是一个例子,使用GSON类库。

@SuppressWarnings("uncheck")
public static T cloneThroughJson(T t){
    Gson gson = new Gson();
    String  json = gson.toJson(t);
    return (T)gson.fromJson(json, t.getClass());
}

// ...
Object cloned = cloneThroughJson(someObject);

标签: Java, serialization

添加新评论