先让我描述一下问题:
我在某Action(struts2.x)-A中写了一个功能P,以当前用户的某个标识F == 1时需要走这个功能,而且这个功能因某些原因已经侵入到了其他一些method中。
顺便一提,A中获得当前用户session的method已经被父类封装好了。
然后我的代码已经push上去了,第二天有人告诉我能不能暂时去掉这个功能。
一个个注释掉太麻烦了,
于是我决定在这个A中override获得当前用户session的method,并将F赋值为0。

于是我只需要来个shallow copy就可以了。
比如我可以这样:
给User来个implements Clonable
然后在getUserInfo()的Override中clone一个出来再赋值setF(0)

但这也许不太好,毕竟我需要动User。
我可以直接使用org.springframework.beans.BeanUtils.copyPropergties(source,target)
看了看源码,里面又是sourcepd又是targetpd,pd是什么?

就当他是用来描述java bean的媒介好了。
当然,他也是shallow copy...


for (PropertyDescriptor targetPd : targetPds) {
  if (targetPd.getWriteMethod() != null &&
    (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
  PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
    if (sourcePd != null && sourcePd.getReadMethod() != null) {
      try {
        Method readMethod = sourcePd.getReadMethod();
        if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
          readMethod.setAccessible(true);
        }
        Object value = readMethod.invoke(source);
        Method writeMethod = targetPd.getWriteMethod();
        if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
          writeMethod.setAccessible(true);
        }
        writeMethod.invoke(target, value);
      } catch (Throwable ex) {
        throw new FatalBeanException("Could not copy properties from source to target", ex);
      }
    }
  }
}

无论如何,这个已经解决我的问题了,A中调用getUserInfo()都是我clone的User,不会影响其他的Action.

但如果我那天用User下某个引用类型的Field的某个simple type的Field做标记呢?
那我得deep clone,平时掌握的类库不多,让我自己解决的话我怎么弄?

也许我可以这样做:


File f = new File("@#$%^&*");
f.createNewFile();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
oos.writeObject(u0); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
u1 = (User)ois.readObject();

光看一小段代码感觉是个简单粗暴的好办法,只不过我得User及其下那些引用类型加上implements Serializable...

后来我找到了这样一个东西:


<dependencies>
<dependency>
<groupId>uk.com.robust-it</groupId>
<artifactId>cloning</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>

可以这样使用:


com.rits.cloning.Cloner cloner = new com.rits.cloning.Cloner();
u1 = cloner.deepClone(u0);
u1.getPet().setName("papapa");
System.out.println(u0);
System.out.println(u1);

输出结果是clone后的u1的pet的名字变成了papapa而作为clone source的u0没有任何变化,这就是deep clone.

忽略clone source是数组的情况,这个类进行deep clone的关键部分如下:


for (final Field field : fields) {
  final int modifiers = field.getModifiers();
  if (!Modifier.isStatic(modifiers)) {
    if (nullTransient && Modifier.isTransient(modifiers)) {
      // request by Jonathan : transient fields can be null-ed
      final Class<?> type = field.getType();
      if (!type.isPrimitive()) {
        field.set(newInstance, null);
      }
    } else {
      final Object fieldObject = field.get(o);
      final boolean shouldClone = (cloneSynthetics || (!cloneSynthetics && !field.isSynthetic())) && (cloneAnonymousParent || ((!cloneAnonymou        sParent && !isAnonymousParent(field))));
      final Object fieldObjectClone = clones != null ? (shouldClone ? cloneInternal(fieldObject, clones) : fieldObject) : fieldObject;
      field.set(newInstance, fieldObjectClone);
      if (dumpClonedClasses && fieldObjectClone != fieldObject) {
        System.out.println("cloned field>" + field + " -- of class " + o.getClass());
      }
    }
  }
}

递归下去找field的引用的引用的引用的引用....然后全是他们newInstance...

Java - 深拷贝技巧的更多相关文章

  1. Java数组技巧攻略

      Java数组技巧攻略 0.  声明一个数组(Declare an array) String[] aArray = new String[5]; String[] bArray = {" ...

  2. 一种c#深拷贝方式完胜java深拷贝(实现上的对比)

    楼主是一名asp.net攻城狮,最近经常跑java组客串帮忙开发,所以最近对java的一些基础知识特别上心.却遇到需要将一个对象深拷贝出来做其他事情,而原对象保持原有状态的情况.(实在是不想自己new ...

  3. java新手抖机灵(java新手技巧)

    java新手抖机灵(java新手技巧) 1.交换两个整数的值 好处是不用定义临时变量,显得代码简洁,提高运行效率 其实也可以用+-*/进行这种运算 比如可以这样: a = a + b; b = a - ...

  4. 偏执却管用的10条Java编程技巧

    本文由 ImportNew - LynnShaw 翻译自 javacodegeeks.欢迎加入翻译小组.转载请见文末要求. 经过一段时间的编码(咦,我已经经历了将近20年的编程生涯,快乐的日子总是过得 ...

  5. Java 深拷贝和浅拷贝 利用序列化实现深拷贝

    Java 深拷贝和浅拷贝 转自:http://www.cnblogs.com/mengdd/archive/2013/02/20/2917971.html 深拷贝(deep clone)与浅拷贝(sh ...

  6. 代码优化:Java编码技巧之高效代码50例

    出处:  Java编码技巧之高效代码50例 1.常量&变量 1.1.直接赋值常量值,禁止声明新对象 直接赋值常量值,只是创建了一个对象引用,而这个对象引用指向常量值. 反例: Long i = ...

  7. Java 小技巧和在Java避免NullPonintException的最佳方法(翻译)

                前几天就g+里面看到有人引用这篇博文.看了一下.受益颇多. 所以翻译过来,希望和大家一起学习.本人英语水平有限,假设有错,请大家指正. 原文地址(须要翻墙):http://ja ...

  8. java 深拷贝与浅拷贝机制详解

    概要: 在Java中,拷贝分为深拷贝和浅拷贝两种.java在公共超类Object中实现了一种叫做clone的方法,这种方法clone出来的新对象为浅拷贝,而通过自己定义的clone方法为深拷贝. (一 ...

  9. 10个调试Java的技巧

    调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试技巧, ...

随机推荐

  1. Linux基础实验(一)

    一)基础实验:1. Unix中常见shell及其命令(shell的缩写)    Bourne shell (sh)      Korn shell (ksh)    C shell (csh)     ...

  2. C# Winform下一个热插拔的MIS/MRP/ERP框架13(窗体基类)

    作为一个ERP数据处理框架,大部分的开发场景都差不多. 理想中,对于通用数据处理,我的步骤如下: 1.为窗体指定数据来源(数据表/查询等): 2.拖入编辑控件,指定绑定字段: 3.结束. 为此,我设计 ...

  3. MkDocs 文档生成逻辑浅析

    Markdown 和 MkDocs 简介 Markdown 的语法简洁明了.学习容易,而且功能比纯文本更强,因此有很多人用它写博客.世界上最流行的博客平台 WordPress 和大型 CMS 如 Jo ...

  4. PL/SQL数据库开发那点事

    PL/SQL数据库开发那点事-->编程,存储程序 在SQL*plus 中编写PL/SQL程序,并在SQL*plus 中执行它, PL/SQL块的代码就存放在SQL*plus的缓冲区中.如果在SQ ...

  5. 实现反转的方法(reverse)

    1.最简单的方法: public static String reverse1(String str) { return new StringBuffer(str).reverse().toStrin ...

  6. NOI.AC省选模拟赛第一场 T1 (树上高斯消元)

    link 很容易对于每个点列出式子 \(f_{x,y}=(f_{x,y-1}+f_{x,y}+f_{x,y+1}+f_{x+1,y})/4\)(边角转移类似,略) 这个转移是相互依赖的就gg了 不过你 ...

  7. 循环神经网络RNN原理

    一.循环神经网络简介 循环神经网络,英文全称:Recurrent Neural Network,或简单记为RNN.需要注意的是,递归神经网络(Recursive Neural Network)的简写也 ...

  8. window.onload和JQuery中$(function(){})的区别即其实现原理

    一.区别 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. 在Jquery中$(function(){ })和$(document).ready(function(){ ...

  9. Openfire服务端源代码开发配置指南[转]

    转自:http://www.micmiu.com/opensource/openfire/openfire-src-config/   本文将图文介绍如何把openfire(以3.8.1为例)源码配置 ...

  10. SQL总结----存储过程

    概念 存储过程(Stored Procedure):已预编译为一个可执行过程的一个或多个SQL语句. 创建存储过程语法 CREATE proc | procedure procedure_name [ ...