【问题标题】:Deep copying Generics in JavaJava中的深度复制泛型
【发布时间】:2017-03-19 02:09:29
【问题描述】:

我有一个编程任务要在 Java 中制作一个通用堆栈,我需要制作一个 newNode T 的深拷贝。我不知道如何制作一个可以访问其自身并输出 i 的深拷贝方法深拷贝。到目前为止,我有这个:

public class Stack<T>
{ 

    private T[] data;
   private int top;
   private int size;
   public Stack( )
   {  top = -1;
      size = 100;
      data = (T[])new Object[100];
   }
   public Stack(int n)
   {  top = -1;
      size = n;
      data = (T[])new Object[n];
   }
   public boolean push(T newNode)
   {  if(top == size-1)
           return false;  // ** overflow error **
       else
       {  top = top +1;
          data[top] = newNode.deepCopy();
          return true;  // push operation successful
       }
   }
   public T pop( )
   {  int topLocation;
       if(top == -1)
           return null;  // ** underflow error **
       else
       {  topLocation = top;
           top = top -1;
           return data[topLocation];
       }
   }
   public void showAll( )
   {  for(int i = top; i >= 0; i--)
         System.out.println(data[i].toString());
   }


}

如何制作 newNode 的深层副本。我很确定我需要该方法的接口,但过去我迷路了。

【问题讨论】:

  • 欢迎来到 SO。请参阅:stackoverflow.com/questions/64036/…。有没有关于T 的其他信息?是否实现clonable接口?
  • @c0der: 是否实现Cloneable 无关紧要。 Cloneable 不提供公共克隆方法;它有不同的用途。
  • @newacct ,正如@c0der 所指出的那样,有关实际T 的更多信息可能会有所帮助,因为当您尝试深度复制具有其他引用的引用时,它会以错误的循环结束。 ......

标签: java generics deep-copy


【解决方案1】:

也许最通用和最直接的解决方案是要求使用代码在构造时提供深度复制例程:

public class Stack<T> {
  ...
  private final Function<T, T> elementCopier;
  public Stack<T>(Function<T, T> elementCopier) {
     // make sure thy are not passing you a null copier:
     this.elementCopier = Objects.requiresNonNull(elementCopier);
     ...
  }
  ...
  public boolean push(T element) {
     ...
     data[top] = elementCopier.apply(element);
     ...
  }
  ...
}

例如,对于一个可克隆的类类型,其中 .clone() 实际上是一个 deepCopy,用户代码如下:

Stack<MyElemClz> stack = new Stack<>(x -> x.clone());
// or:
Stack<MyElemClz> stack = new Stack<>(MyElemClz::clone);
...
MyElemClaz elem = ...;
...
stack.push(elem);

如果类型是像 String 这样的常量简单对象,则不需要克隆,在这种情况下,用户将标识 lambda x -&gt; x 表示为 复印机:

Stack<String> stack = new Stack<>(x -> x)

如果用户坚持复制,即使类是常量,你也可以强制它:

Stack<String> stack = new Stack<>(x -> new String(x))
// or
Stack<String> stack = new Stack<>(String::new)

【讨论】:

    【解决方案2】:

    可以使用ObjectOutputStream/ObjectInputStream 制作深拷贝。 然后不会存储对象(对可变字段的引用),而是堆栈中的序列化字节。

    继续。

    ObjectOutputStream 进行深拷贝。

    【讨论】:

      【解决方案3】:

      如果你想使用界面,或者你不喜欢 Valentin 的方法,你可以这样做:

      interface Copiable<T> {
          T deepCopy();
      }
      
      public class Stack<T extends Copiable<T>> {
      ...
      }
      

      然后对放入堆栈的对象实现deepCopy 方法,即

      class A implements Copiable<A> {
        @Override
        public A deepCopy() {
          // ... your copy code here
        }
      }
      
      Stack<A> stack = new Stack<>();
      

      等等

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-18
        • 2011-07-25
        • 2011-06-17
        • 1970-01-01
        • 2015-02-28
        • 2011-02-28
        • 1970-01-01
        相关资源
        最近更新 更多