现在的位置: 首页 > 综合 > 正文

Java Generic Deep Copy

2013年08月26日 ⁄ 综合 ⁄ 共 5881字 ⁄ 字号 评论关闭

原文:http://www.genericdeepcopy.com/

Java Generic Deep Copy 

简介:

Generic Deep Copy 是一个用于深度拷贝的java实用程序。这些被拷贝的对象不需要去实现Serializable,Cloneable或者任何其他的接口。基本上,这个程序可以深度拷贝任何java对象。在很多场合,使用它可以节省时间和精力。

使用场景:

无法进行系列化(non Serializable)的类并且它们来自第三方jars库,因此对应的源码无法改变;
无法进行系列化(non Serializable)的类并且有数百个类牵涉其中,因此手动更新它们是非常耗时的;
相对影子拷贝/浅复制(shallow copying),研究java反射和深度拷贝;
测试-创建一个拷贝,测试对象的改变,创建一个新的拷贝,再测试对象的改变。确保这些改变是一样的,或者避免重新初始化一个主要实例。

这个程序还需要努力去改进,因此非常期待您的反馈。如果您下载并且试用了这个程序,请留下评论!这是该程序在各个场景下被测试使用的唯一途径。

许可证:

由 Aaron Johnson 编写的java程序Generic Deep Copy遵守modified Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License许可证。对于引用作品或者任何商业目的的商业授权,请参考联系页面或者联系销售。

基本信息
这款软件对于个人是可以免费使用的,并且不能用于商业(用于盈利)目的。

最近的代码拷贝可以在以下网站找到:
 http://www.genericdeepcopy.com.

允许:

  • 你可以复制,修改并且传播这个程序。
  • 在个人使用或者非商业使用情况下,你可以使用这个程序。

限制:

  • 这个提醒必须保持完整,并且一直和代码一起发布,即使用于个人使用。
  • 你必须按照作者或者许可证的方式来署名该作品。(但是,并不是任何情况下,他们赞成你或者你对作品的使用。)
  • 你不能将这个作品用于商业目的。如果需要进行商业使用,请联系作者。
  • 如果你在这个作品之上进行更改,转变,或者构建,你必须将最后的作品至于和本作品一样的许可证之下。
  • 你不可以对这个软件进行逆向工程,反编译,或者反汇编,也不能试图使用其他的方式来活的源代码。

详细信息:

http://creativecommons.org/licenses/by-nc-sa/3.0/ (Summary)
http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode (Detailed)


下载:

从这个网站下载该软件,代表你已经同意这些许可证协议,包括你同意不会将该作品用于任何商业或者盈利的目的。
在下载之前,请阅读许可证协议。

Generic Deep Copy 需要 Java 1.5及以上。

点击下载:
DeepCopyUtil-1.4

实例和测试样例

使用这个程序就像你在下面的测试样例中见到的一样简单。由于使用assertTrue() 和 assertFalse() 方法,jUnit会被用到。 调整了注释使得代码只占用极少数行。

基本用法:

/** Basic usage of the utility.
 * @throws Exception */
public void testBasicUsage() throws Exception {
    DeepCopyUtil deepCopyUtil = new DeepCopyUtil(); // create deep copies of objects.
    
    // create an object
    CustomClass customObject = new CustomClass();
    
    // create a copy of the object
    CustomClass copy = deepCopyUtil.deepCopy(customObject);
    
    assertFalse(customObject == copy);
}

各种类类型

这个例子演示了简单类的深度拷贝。

/** Test that deep copy correctly copies basic object types.
 * @throws Exception */
public void testVariousTypes() throws Exception {
    DeepCopyUtil deepCopyUtil = new DeepCopyUtil(); // used to create deep copies of objects.
    Calendar cal = Calendar.getInstance();
    int intArray[] = {1,2,3};
    Integer integerArray[] = new Integer[]{1,2,3};
    List<String> stringListFromArray = Arrays.asList(new String[]{"one", "two"});
    List<String> normalList = new ArrayList<String>();
    normalList.add("weeeeee");

    Calendar calCopy = deepCopyUtil.deepCopy(cal); // create deep copies of objects.
    int intArrayCopy[] = deepCopyUtil.deepCopy(intArray);
    Integer integerArrayCopy[] = deepCopyUtil.deepCopy(integerArray);
    List<String> stringListFromArrayCopy = deepCopyUtil.deepCopy(stringListFromArray);
    List<String> normalListCopy = deepCopyUtil.deepCopy(normalList);
    
    assertFalse(cal == calCopy); // assure instances are different.
    assertFalse(intArray == intArrayCopy);
    assertFalse(integerArray == integerArrayCopy);
    assertFalse(stringListFromArray == stringListFromArrayCopy);
    assertFalse(normalList == normalListCopy);
    
    assertTrue(cal.equals(calCopy)); // assure values are the same.
    for (int i = 0; i < intArray.length; i++) {
        assertTrue(intArray[i] == intArrayCopy[i]); // int's use ==
    }
    for (int i = 0; i < integerArray.length; i++) {
        assertFalse(integerArray[i] == integerArrayCopy[i]); // Integers use .equals
        assertTrue(integerArray[i].equals(integerArrayCopy[i]));
    }
    for (int i = 0; i < stringListFromArray.size(); i++) { // instances are different, values are equal.
        assertFalse(stringListFromArray.get(i) == stringListFromArrayCopy.get(i));
        assertTrue(stringListFromArray.get(i).equals(stringListFromArrayCopy.get(i)));
    }
    for (int i = 0; i < normalList.size(); i++) { // instances are different, values are equal.
        assertFalse(normalList.get(i) == normalListCopy.get(i));
        assertTrue(normalList.get(i).equals(normalListCopy.get(i)));
    }
    
    assertTrue(cal.getClass() == calCopy.getClass()); // assure class types are the same.
    assertTrue(intArray.getClass() == intArrayCopy.getClass());
    assertTrue(integerArray.getClass() == integerArrayCopy.getClass());
    assertTrue(stringListFromArray.getClass() == stringListFromArrayCopy.getClass());
    assertTrue(normalList.getClass() == normalListCopy.getClass());
}

大型 LinkedList

深度拷贝超过包含100,000个对象的LinkedList

/** Assure that a LinkedList of 100,000 elements can be deep copied. <br/>
 * Add -Xms512m and -Xmx1536m to the JVM args to see this work with 1,000,000.
 * @throws Exception */
public void testLinkedList() throws Exception {
    DeepCopyUtil deepCopyUtil = new DeepCopyUtil(); // used to create deep copies of objects.
    List<Integer> lst = new LinkedList<Integer>(); // Create a linked list of Integers.
    for (int i = 0; i < 100000; i++) {
        lst.add(i);
    }
    
    List<Integer> copyOfList = deepCopyUtil.deepCopy(lst); // create a deep copy
    
    assertTrue(copyOfList.size() == lst.size()); // test that the lists are the same size.
    assertFalse(copyOfList == lst); // test that the lists are not the same lists.
    
    // create some iterators instead of using list.get(), because we're using a LinkedList
    // and that would be slow.
    Iterator<Integer> origIt = lst.iterator();
    Iterator<Integer> copyIt = copyOfList.iterator();
    Integer origInt, copyInt;

    while (origIt.hasNext()) { // compare each of the items in both lists
        origInt = origIt.next();
        copyInt = copyIt.next();

        assertFalse(origInt == copyInt); // the lists should not be the same instance.
        assertTrue(origInt.equals(copyInt)); // the inner values should be the same.
    }
}

循环引用

深度拷贝一个循环引用的类。这个类包含很多对自己的引用并且仍然能够被正确拷贝。测试显示,这些循环引用仍然能够保持一样的关系。(例如:内部实例仍然能够正确的引用外部的类实例)

package test.com.ajexperience.utils.deepcopyutil;

import junit.framework.TestCase;

import com.ajexperience.utils.DeepCopyUtil;

public class DeepCopyTestSimpleCircle extends TestCase {
    
    public InnerClass outerToInner = new InnerClass(); // an instance of the inner class
    public DeepCopyTestSimpleCircle pointerToSelf; 
    
    public class InnerClass { // an inner class with a link to the outer class
        DeepCopyTestSimpleCircle innerToOuter;
    }

    public DeepCopyTestSimpleCircle() {
        outerToInner.innerToOuter = this; // link the inner class to the outer class
        this.pointerToSelf = this; // self reference
    }
    
    public static void main(String args[]) throws Exception {
        DeepCopyUtil deepCopyUtil = new DeepCopyUtil(); // used to create deep copies of objects.
        DeepCopyTestSimpleCircle simpleCircle = new DeepCopyTestSimpleCircle(); // create an instance.

        DeepCopyTestSimpleCircle copy = deepCopyUtil.deepCopy(simpleCircle); // deep copy the object.
        
        assertFalse(simpleCircle == copy); // test that they are not equal.
        
        // test that the circular references are in tact.
        assertTrue(copy == copy.outerToInner.innerToOuter);
        assertTrue(copy == copy.pointerToSelf);
    }
}

抱歉!评论已关闭.