【问题标题】:How to use the copy constructor correctly in Java?如何在 Java 中正确使用复制构造函数?
【发布时间】:2021-03-17 17:14:20
【问题描述】:

我在嵌入式 C 方面有比较好的经验后开始学习 java,并尝试应用一些简单的练习来确保对 java 主题的良好理解, 这是一个简单的练习,我创建了一个复制构造函数来基于现有对象创建一个新对象:

public class A {
    private int a = 2;
    private int b = 2;
    public A(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public A(A r) {
        r.a=r.a + this.a;
        r.b=r.b + this.b;
    }
    String getDetail() {
        return "{"+a+","+b+"}";
    }
    public static void main(String[] args) {
        A r = new A(1,1);
        A a = new A(r);
        System.out.println(a.getDetail());
    } 
}

这是我期望的输出:{3,3}

但这是我得到的:{2,2}

你能解释一下为什么吗?提前致谢!

【问题讨论】:

  • 你认为r.a=r.a + this.a; 会做什么?
  • 这会将默认值“2”添加到“r.a”
  • 你要修改的是r还是a(构造函数中的this)?

标签: java oop copy-constructor


【解决方案1】:

复制构造函数的定义是最终将指定为参数的实例的相同特征复制到该类的新对象,例如:

class Person {
    private String name;
    private int age;

    public Person (String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Person (Person person) {
        this.name = person.name;
        this.age = age;
    }
}
Person john = new Person("John", 20);
Person johnDuplicated = new Person(john);
System.out.println(john.name + " " + john.age); //Output: John 20
System.out.println(johnDuplicated.name + " " + johnDuplicated.age); //Output: John 20

在您的情况下,您已经将实例变量 a 和 b 初始化为 2,这将允许为上述实例变量默认为类 A 的所有实例分配值 2。通过提供以下内容继续实例化 A 类:

A r = new A(1, 1);
A a = new A(r);

当您在类 A 的构造函数中引用参数实例变量而不是当前实例变量(即 'this' 关键字表示的内容)时,上述内容将产生 {1,1} 作为输出。

为了允许您期望的行为,将 A 类修改为以下内容:

public A (A r) {
    this.a += r.a;
    this.b += r.b;
}

因此输出应为:

{3,3}

【讨论】:

    【解决方案2】:

    你的构造错误,这里是解决办法

    public A(A r) {
        this.a = r.a + this.a;
        this.b = r.b + this.b;
    }
    

    但它不是拷贝的构造函数。副本的构造函数是

    public A(A r) {
        this.a = r.a;
        this.b = r.b;
    }
    

    【讨论】:

    • 在这些作业的右侧重用this.athis.b 有点奇怪。事实上,this.athis.b 的原始(初始化)值总是被覆盖。保留它们没有任何意义。取而代之的是this.a = r.a + 2;
    • 您的解决方案违反了 DRY。如果你想改变 '2' 常数,你应该在 2 个地方改变它。我给出了原始问题的答案。但我认为复制的构造函数应该使用 this.a = r.a 和 this.b = r.a,然后应该在复制的对象上调用 increamentA(2)incrementB(2) - 这是最好的解决方案,但不是原始的答案问题。
    • 2 还用在什么地方?
    • 1-st in field initializer private int a = 2;, 2-nd in this.a = r.a + 2
    • 对,这就是我在第一条评论中的意思。字段初始值设定项中的原始值永远不会被使用。也可能是private int a;
    猜你喜欢
    • 2014-03-24
    • 2023-03-31
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多