默认拷贝构造函数示例 - 极悦
首页 课程 师资 教程 报名

默认拷贝构造函数示例

  • 2022-09-08 10:33:49
  • 599次 极悦

在 Java 中,我们如何复制一个对象呢?我们都知道Java Object类中的clone方法,该方法用于克隆对象。

默认复制构造函数

假设我们有一个名为Student的实体,它拥有另一个名为Result的实体。

结果 POJO

公共 最终 类 结果{
私有 最终 int 标记;
公共 结果(最终 整数 标记){
这个。标记 = 标记;
}
公共 int  getMarks () {
返回 这个。标记;
}
@覆盖
公共 字符串 toString () {
返回 更多对象。toStringHelper ( this.getClass ( )) 。添加(“标记”,这个。标记)。toString ();
}
}

学生 POJO

公共 期末 班 学生{
私有 最终 字符串 名称;
私人 最终 结果 结果;
公共 学生(最终 字符串 名称,最终 结果 结果){
checkNotNull (名称);
checkNotNull (结果);
这个。名称 = 名称;
这个。结果 = 结果;
}
公共 字符串 getName () {
返回 这个。名称;
}
公共 结果 getResult () {
返回 这个。结果;
}
@覆盖
公共 字符串 toString () {
返回 更多对象。toStringHelper ( this.getClass ( )) 。添加(“名称”,这个。名称)。添加(“结果”,这个。结果)。toString ();
}
}

因此, Student的每个对象都将持有一个指向实际Result对象的指针。

应用程序客户端

公共 最终 类 DefalutCopyConstructor {
公共 静态 无效 主要(最终 字符串[]参数){
最终 结果 结果 = 新 结果(50);
final  Student  student  =  new  Student ( "Sam" , result );
系统。出来。println (学生);
}
}

如果您运行前面的代码,您可以获得一个Student对象,该对象包含对Result对象的引用。现在,如果想创建另一个对象,可以像在前面的示例中那样创建它。

公共 最终 类 DefalutCopyConstructor {
公共 静态 无效 主要(最终 字符串[]参数){
最终 结果 result1  = 新 结果( 50 );
final  Student  student1  =  new  Student ( "Sam" , result1 );
最终 结果 result2  = 新 结果( 50 );
final  Student  student2  =  new  Student ( "Dean" , result2 );
系统。出来。打印(学生1);
系统。出来。打印(学生2);
}
}

现在,我们创建了另一个学生对象。如果您使用相等运算符进行检查,它将报告错误,因为两个引用(student1 和 student2)都指向堆中的不同对象。

如果我们想将 student1 的对象复制到 student2 的引用中,会尝试编写如下语法。

公共 最终 类 DefalutCopyConstructor {
公共 静态 无效 主要(最终 字符串[]参数){
最终 结果 result1  = 新 结果( 50 );
final  Student  student1  =  new  Student ( "Sam" , result1 );
最终 学生 student2  = 新 学生( student1 );
系统。出来。打印(学生1);
系统。出来。打印(学生2);
}
}

这显然会报编译错误。

构造 函数Student ( Student )未定义_ 

但是想想,Java 可以给我们一个像这样的默认复制构造函数,但它没有。

为什么?因为浅拷贝的危险

浅拷贝

在这里,student1 指的是一个包含Result对象引用的Student对象。现在,student2 将引用一个全新的Student对象,但这个新的Student对象仍将包含对旧Result对象的Result引用。因此,您可以清楚地看到对象不是深度复制而是引用。

由于复制对象的风险,Java 没有提供默认复制构造函数。

解决方案(深拷贝)

然后我们可以尝试实现我们自己的复制构造函数来深度复制对象。让我们尝试实现它。

带有复制构造函数的结果 POJO

公共 最终 类 结果{
私有 最终 int 标记;
公共 结果(最终 整数 标记){
这个。标记 = 标记;
}
公共 结果(最终 结果 结果){
这个。标记 = 结果。获取标记();
}
公共 int  getMarks () {
返回 这个。标记;
}
@覆盖
公共 字符串 toString () {
返回 更多对象。toStringHelper ( this.getClass ( )) 。添加(“标记”,这个。标记)。toString ();
}
}

带有复制构造函数的学生 POJO

公共 期末 班 学生{
私有 最终 字符串 名称;
私人 最终 结果 结果;
公共 学生(最终 字符串 名称,最终 结果 结果){
checkNotNull (名称);
checkNotNull (结果);
这个。名称 = 名称;
这个。结果 = 结果;
}
公共 学生(最终 学生 学生){
这个。姓名 = 学生。获取名称();
这个。结果 = 新 结果(学生。getResult ());
}
公共 字符串 getName () {
返回 这个。名称;
}
公共 结果 getResult () {
返回 这个。结果;
}
@覆盖
公共 字符串 toString () {
返回 更多对象。toStringHelper ( this.getClass ( )) 。添加(“名称”,这个。名称)。添加(“结果”,这个。结果)。toString ();
}
}

客户端应用程序

公共 最终 类 DefalutCopyConstructor {
公共 静态 无效 主要(最终 字符串[]参数){
最终 结果 result1  = 新 结果( 50 );
final  Student  student1  =  new  Student ( "Sam" , result1 );
最终 学生 student2  = 新 学生( student1 );
系统。出来。打印(学生1);
系统。出来。打印(学生2);
}
}

由于这个实现,我们完全摆脱了浅拷贝问题。这意味着现在,我们可以精确复制每个对象,无论是Student对象还是Result对象。Student对象的副本将不再引用任何其他Student对象包含的Result对象。相反,它将包含一个新的Result对象引用。

以上就是关于“默认拷贝构造函数示例”介绍,大家如果想了解更多相关知识,可以关注一下极悦的Java基础教程技术文档,里面还有更丰富的知识等着大家去学习,希望对大家能够有所帮助。

选你想看

你适合学Java吗?4大专业测评方法

代码逻辑 吸收能力 技术学习能力 综合素质

先测评确定适合在学习

在线申请免费测试名额
价值1998元实验班免费学
姓名
手机
提交