如何在Java中正确使用复制构造函数?

How to use the copy constructor correctly in Java?

提问人:Mohammed G 提问时间:3/18/2021 更新时间:3/18/2021 访问量:251

问:

我在嵌入式 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}

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

Java OOP 复制构造函数

评论

1赞 Sotirios Delimanolis 3/18/2021
你认为有什么作用?r.a=r.a + this.a;
0赞 Mohammed G 3/18/2021
这会将 defaut 值“2”添加到“r.a”中
1赞 Sotirios Delimanolis 3/18/2021
你是想修改还是(在构造函数中)?rathis

答:

0赞 Vitalii 3/18/2021 #1

你的构造函数是错误的,这是解决方案

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

但它不是复制的构造函数。copy 的构造函数是

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

评论

0赞 Sotirios Delimanolis 3/18/2021
重复使用和在这些作业的右侧有点奇怪。事实上,和 的原始(初始化)值总是被覆盖。保留它们是没有意义的。取而代之的是.this.athis.bthis.athis.bthis.a = r.a + 2;
0赞 Vitalii 3/18/2021
您的解决方案违反了 DRY。如果要更改“2”常量,则应在 2 个位置更改它。我给出了原始问题的答案。但我认为复制的构造函数应该使用 this.a = r.a 和 this.b = r.a,在它之后,应该在复制的对象上调用 - 这是一个最好的解决方案,但不是原始问题的答案。increamentA(2)incrementB(2)
0赞 Sotirios Delimanolis 3/18/2021
2 还用在哪里?
0赞 Vitalii 3/18/2021
1-ST 字段初始值设定项,2-ND 输入private int a = 2;this.a = r.a + 2
2赞 Sotirios Delimanolis 3/18/2021
是的,这就是我在第一条评论中的意思。从不使用字段初始值设定项中的原始值。还不如.private int a;
1赞 Justin Joseph 3/18/2021 #2

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

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);

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

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

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

因此,输出应为:

{3,3}