【问题标题】:Object deep cloning without Java reflection没有 Java 反射的对象深度克隆
【发布时间】:2015-09-29 15:56:35
【问题描述】:

在没有 Java 反射的情况下进行深度对象克隆的可能性是什么?我使用了使用反射的对象克隆库,但 AppEngine 不允许这样做。

所以我现有的与 Tomcat 一起工作的应用程序不起作用。

更新:

Dozer 库似乎是最好的选择:

Mapper mapper = new DozerBeanMapper();
DestinationObject destObject =  mapper.map(sourceObject, DestinationObject.class);

问题是,如果我不需要自定义映射,是否可以按原样执行上述操作?

例如:

Cat cat = new Cat();

Mapper mapper = new DozerBeanMapper();
Cat newCat =  mapper.map(cat, Cat.class);

更新:

当我使用 Dozer 运行我的应用程序时,我收到此错误:

Caused by: java.lang.NoSuchMethodError: org.apache.commons.lang.StringUtils.contains(Ljava/lang/String;Ljava/lang/String;)Z
    at org.dozer.util.ResourceLoader.getResource(ResourceLoader.java:53)
    at org.dozer.util.DefaultClassLoader.loadResource(DefaultClassLoader.java:44)
    at org.dozer.config.GlobalSettings.loadGlobalSettings(GlobalSettings.java:116)
    at org.dozer.config.GlobalSettings.<init>(GlobalSettings.java:67)
    at org.dozer.config.GlobalSettings.<clinit>(GlobalSettings.java:46)

看起来我遗漏了一些东西,虽然我使用 Maven 添加了 Dozer。

【问题讨论】:

  • 我曾经对此和Clone was the fastestsecond was reflectionlast one was serialization进行基准测试。所以我总是使用clonecopy()
  • @AmitD 即使我在类中添加了 Cloneable 接口,它仍然没有 clone() 或 copy()
  • 为什么不写一个适当的复制函数,就像你应该做的那样?
  • @xybrek 你需要从 Object 类中重写 clone() 方法或提供 copy constructors 然后你不需要克隆

标签: java


【解决方案1】:

您是否考虑过使用Dozer

[来自他们的网站]

Dozer 是一个 Java Bean 到 Java Bean 的映射器,它递归地复制数据 从一个对象到另一个对象。通常,这些 Java Bean 将是 不同的复杂类型。

Dozer 支持简单的属性映射,复杂的类型映射, 双向映射,隐式-显式映射,以及 递归映射。这包括映射集合属性 还需要在元素级别进行映射。

Dozer 不仅支持属性名之间的映射,还支持 类型之间自动转换。大多数转换场景是 支持开箱即用,但推土机还允许您指定自定义 通过 XML 进行转换。

【讨论】:

  • 您与 Dozer 有合作关系吗?只是好奇。
  • @duffymo 一点也不。我刚刚在几个项目中使用了该框架,看起来它可能适合 xybrek 正在尝试做的事情。
  • 好的,谢谢。我喜欢问人们什么时候推荐东西。隐藏的偏见是显而易见的。
  • @DomenicD。您的答案似乎符合我需要的解决方案,但是由于您已经使用过它,所以我几乎没有问题,请参阅我更新的问题。干杯!
  • 由于某种原因,您使用的是不支持 contains(String,String) 的过时或真正新版本的 commons-lang。确保您使用的是 2.5 版。
【解决方案2】:

好吧,您总是可以手动进行深度克隆,只需覆盖类中的 clone() 方法即可。非常重复的工作,但可行。而且也比使用反射更有效。

【讨论】:

    【解决方案3】:

    你可以试试 ObjectOutputStream/ObjectInputStream。这使用反射,但您的 SecurityManager 可能允许它,因为您没有直接调用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 2017-02-23
      • 2023-04-01
      • 2012-06-05
      • 2017-07-12
      相关资源
      最近更新 更多