当前位置: 首页 > wzjs >正文

湛江论坛建站模板苏州网页设计培训

湛江论坛建站模板,苏州网页设计培训,运动网页设计,北京学网站开发目录 谨慎重写clone方法重写clone()支持深拷贝带来的问题 合适的深拷贝 首先,对于不可变的类,我们不应该实现Cloneable接口,因为不可变类不需要拷贝,直接引用即可,实现Cloneable接口只会造成浪费。 对于Java可变类来说…

目录

  • 谨慎重写clone方法
    • 重写clone()支持深拷贝带来的问题
  • 合适的深拷贝

首先,对于不可变的类,我们不应该实现Cloneable接口,因为不可变类不需要拷贝,直接引用即可,实现Cloneable接口只会造成浪费。

对于Java可变类来说,拷贝分为浅拷贝与深拷贝。

  • 浅拷贝(Shallow Copy)
    只复制第一层,嵌套对象共享引用,适合简单场景。常见的Object.clone()方法就是浅拷贝。
  • 深拷贝(Deep Copy)
    递归复制所有层,完全独立,适合复杂数据。一般需要手动实现或使用第三方依赖。

谨慎重写clone方法

Cloneable是一个标记接口(marker interface),没有方法声明。clone方法定义在Object类中,且是protected,需要子类显式重写为public。

Object.clone()默认执行浅拷贝,不适用于需要深拷贝的场景。如果重写clone()来支持深拷贝会怎么样呢?会不会有问题?

重写clone()支持深拷贝带来的问题

  • 代码复杂,维护成本高
    必须确保嵌套对象和对象的元素支持clone,需要递归处理所有字段。
    嵌套多层时逐层克隆容易出错且难以维护、耦合高。

  • 不可变字段
    final字段无法在clone中赋值,限制使用场景。

  • 异常处理复杂
    需要处理CloneNotSupportedException 异常,必须try-catch。

// 需要捕获异常或抛出
try {Person cloned = (Person) original.clone();
} catch (CloneNotSupportedException e) {e.printStackTrace();
}

如果一个类实现了 Cloneable 接口,那么 Object 的 clone 方法将返回该对象的逐个属性(field-by-field)拷贝,属性中包含对象(嵌套对象)也需要实现Cloneable接口,否则会抛出 CloneNotSupportedException 异常。

因此,虽然可以重写clone()来支持深拷贝,但是并不建议这样做。

合适的深拷贝

  • 手动递归+clone()方法
    递归调用clone方法(),可以结合Stream API。如常见的List深拷贝,借助主流工具包Google Guava 的 Lists.newArrayList()然后clone():
// 使用 Guava 和手动 clone
List<Person> deepCopy = Lists.newArrayList(originalList.stream().map(p -> (Person) p.clone()) // 假设 Person 实现 Cloneable.toList()
);
  • 使用构造函数拷贝
    《Effective Java》推荐的方式。通过构造函数创建新对象,递归复制字段。
    这样可以支持final字段,逻辑清晰,易于维护和扩展。但是需要为每个类编写拷贝逻辑。

  • 使用序列化方式
    通过序列化(如ObjectOutputStream)将对象转为字节流,再反序列化生成副本。
    这种方式性能开销大,且需要对象类实现Serializable。
    可以自己实现,也可以使用第三方的。
    如Apache Commons Lang 的 SerializationUtils

import org.apache.commons.lang3.SerializationUtils;// 使用 Apache Commons 的 SerializationUtils
List<Person> deepCopy = SerializationUtils.clone(originalList);

Jackson实现了不需要实现Serializable接口的方式,使用JSON序列化,性能较低

import com.fasterxml.jackson.databind.ObjectMapper;ObjectMapper objectMapper = new ObjectMapper();
List<Person> deepCopy = objectMapper.readValue(objectMapper.writeValueAsString(originalList),new TypeReference<List<Person>>() {}
);
  • 简单场景:构造函数方式,代码简洁。
  • 高性能需求:手动实现 Cloneable 接口,控制深拷贝逻辑。
  • 复杂嵌套对象:序列化方法+第三方工具(如 SerializationUtilsJackson),自动处理嵌套对象。

《Effective Java》一书中提到:

如果你继承一个已经实现了 Cloneable 接口的类,你别无选择,只能实现一个行为良好的 clone 方法。 否则,通常你最好提供另一种对象复制方法。 对象复制更好的方法是提供一个复制构造方法或复制工厂。

即,推荐使用构造方法或者复制工厂。

// Copy constructor
public Yum(Yum yum){...};// Copy factory
public static Yum newInstance(Yum yum){...};

这两种方式更为灵活、不受接口实现、类型、final的限制。

另外附一段构造函数+序列化例子


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;// 嵌套对象类
class InnerObject implements Serializable {private int value;public InnerObject(int value) {this.value = value;}public int getValue() {return value;}public void setValue(int value) {this.value = value;}// 拷贝构造函数public InnerObject(InnerObject other) {this.value = other.value;}
}// 外层对象类
class OuterObject implements Serializable {private int number;private InnerObject inner;private List<Integer> numbers;public OuterObject(int number, InnerObject inner, List<Integer> numbers) {this.number = number;this.inner = inner;this.numbers = numbers;}public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}public InnerObject getInner() {return inner;}public List<Integer> getNumbers() {return numbers;}// 拷贝构造函数(深拷贝)public OuterObject(OuterObject other) {this.number = other.number;this.inner = new InnerObject(other.inner); // 深拷贝嵌套对象this.numbers = new ArrayList<>(other.numbers); // 深拷贝集合}// 序列化实现深拷贝public OuterObject deepCopyViaSerialization() {try {// 序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);// 反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (OuterObject) ois.readObject();} catch (IOException | ClassNotFoundException e) {throw new RuntimeException("Deep copy failed", e);}}
}public class DeepCopyExample {public static void main(String[] args) {// 创建原始对象InnerObject inner = new InnerObject(10);List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3));OuterObject original = new OuterObject(100, inner, numbers);// 拷贝构造函数深拷贝OuterObject copyConstructor = new OuterObject(original);// 序列化深拷贝OuterObject copySerialized = original.deepCopyViaSerialization();// 修改副本copyConstructor.setNumber(888);copyConstructor.getInner().setValue(444);copyConstructor.getNumbers().set(0, 999);copySerialized.setNumber(777);copySerialized.getInner().setValue(333);copySerialized.getNumbers().set(0, 666);// 输出结果System.out.println("原始对象: number=" + original.getNumber() +", inner.value=" + original.getInner().getValue() +", numbers=" + original.getNumbers());System.out.println("拷贝构造: number=" + copyConstructor.getNumber() +", inner.value=" + copyConstructor.getInner().getValue() +", numbers=" + copyConstructor.getNumbers());System.out.println("序列化拷贝: number=" + copySerialized.getNumber() +", inner.value=" + copySerialized.getInner().getValue() +", numbers=" + copySerialized.getNumbers());}
}
http://www.dtcms.com/wzjs/841672.html

相关文章:

  • 网站建设需要固定ip地址吗新型电商平台有哪些
  • 怎么查看网站是否被收录天河营销型网站建设
  • 微信公众号做网站wordpress没显示已发布
  • 龙游建设工程信息网站西安软件开发公司排行
  • 做平面什么网站的素材不侵权百度公司招聘官网最新招聘
  • 手机网投网站建设wordpress固定连接文件
  • 创意设计师个人网站手机支持wordpress
  • 怎么删除织梦做的网站清除wordpress标志
  • 手机网站建设教程精品源码分享的网站
  • 深圳专业建站系统建站公司音乐网站建立
  • 影视网站的设计与实现橫山区建设局网站
  • 邯郸网站制作外包深圳南头高端网站建设
  • 合肥建设局网站首页3d动画制作软件中文版
  • 网站频道运营怎么做html怎么做网页框架
  • 英文杭州网站建设国产前端框架 做网站
  • 怎样在百度免费做网站购物网站开发背景及目的
  • 医院网站建设 中企动力wordpress弹窗预览
  • 科技企业网站设计制作做绒毛鉴定网站
  • 襄汾县住房和建设局网站汕头市区
  • html5移动端手机网站开发流程图2008 iis搭建网站
  • joomla 2.5:你的网站建设_使用与管理 下载电子工程师资格证
  • 网站页面布局模板合肥住房和城乡建设部网站
  • 建网站需要什么资料长沙百度推广运营公司
  • 织梦网站开发视频教程开发制作一个网站
  • 企业服务工作站seo推广软件排行榜
  • 苏州精品网站建设中建国际建设有限公司官网
  • 自动做图在线网站贵州网站建设系统
  • 国际网站模板小程序开发平台竞品分析
  • 格力网站建设首页wordpress知更鸟打赏
  • 网站建设的看法有哪些怎么做网站扫描