Java 当第一次传递给构造函数的数组被更新时

Java 当第一次传递给构造函数的数组被更新时,java,Java,当构造函数参数是列表并且列表通过外部函数更新时,该过程是如何进行的?当参数为数组或列表时,存在“按引用传递”系统。但是对象是如何更新的?是否使用了复制构造函数,或者如何使用 让我们假设我们有两个用户定义的类Point和Curve。我们用点对象填充了列表。然后我们用点列表构造曲线对象 List<Point> points=new ArrayList<>(); points.add(Point(0,1)); points.add(Point(0,0)); Curve c=ne

当构造函数参数是列表并且列表通过外部函数更新时,该过程是如何进行的?当参数为数组或列表时,存在“按引用传递”系统。但是对象是如何更新的?是否使用了复制构造函数,或者如何使用

让我们假设我们有两个用户定义的类Point和Curve。我们用点对象填充了列表。然后我们用点列表构造曲线对象

List<Point> points=new ArrayList<>();
points.add(Point(0,1));
points.add(Point(0,0));
Curve c=new Curve(points);
points.add(Point(1,1));

曲线对象是如何受到影响的?

c本质上是指向点对象的指针。意思是c的“值”内部包含类中某个“points”对象的地址


从这里开始,您在points对象中所做的更改将反映到c对象。

在java中只有一个
按值传递引用
,但没有纯
按引用传递
。如果
曲线
将原始值存储到
的参考中,并且
未重新初始化,则您仍在使用相同的参考,因此
c
中的
列表
也将更改(它仍然是相同的参考)

下面是一个小示例,它应该向您展示何时使用同一引用,何时不使用

public class Curve{

    private List<Point> points = new ArrayList<>(0);

    public Curve(List<Point> points) {
        this.points = points;
    }

    public Curve(List<Point> points, boolean flag) {
        this.points.addAll(points);
    }

    void print() {
        for(Point p : points) {
            System.out.println(p);
        }
    }

    public static class Point {
        int x;
        int y;
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "X = " + x +"\nY = " + y ;
        }

    }

    public static void main(String[] args) {
        List<Curve.Point> points = new ArrayList<Curve.Point>(0);
        points.add(new Curve.Point(0,0));
        points.add(new Curve.Point(0,1));
        // Care for compiler error just one should be used
        Curve c = new Curve(points,true); // Using this constructor copies the elements and the folloing add wont affect c
        Curve c = new Curve(points); // Using this constructor uses the same list so the following add will affect c
        points.add(new Curve.Point(1,1));
        c.print();
    }
}
公共类曲线{
私有列表点=新的ArrayList(0);
公共曲线(列表点){
这个点=点;
}
公共曲线(列表点,布尔标志){
this.points.addAll(点);
}
作废打印(){
对于(点p:点){
系统输出println(p);
}
}
公共静态类点{
int x;
int-y;
公共点(整数x,整数y){
这个.x=x;
这个。y=y;
}
@凌驾
公共字符串toString(){
返回“X=”+X+“\nY=”+y;
}
}
公共静态void main(字符串[]args){
列表点=新的ArrayList(0);
添加(新曲线点(0,0));
添加点(新曲线点(0,1));
//注意编译器错误只应使用一个
Curve c=新曲线(points,true);//使用此构造函数复制元素,下面的add不会影响c
曲线c=新曲线(点);//使用此构造函数使用相同的列表,因此以下添加将影响c
添加(新曲线点(1,1));
c、 打印();
}
}

*
点。添加
typo
点。添加
曲线对象现在在列表中有3个点。java中的所有内容都是按值传递的,curve对象的引用与
points
不同,而是指向同一列表。@user3719857如果不查看
curve
的代码,我们就无法完全知道这是真的。如果构造函数正在制作列表的深度副本,那么添加到
不会影响它。@Tgsmith61591实际上这就是我要寻找的答案。谢谢你这是错的
c
不是指向
点的指针,而是它自己的对象<代码>点
只是作为参数传递给
曲线
,我们不能断言
的引用保留在
曲线
内,而不查看
曲线
类的源代码(或查看
添加
操作后
c
的影响)。如果构造器正在制作列表的深度副本,那么添加到点不会影响它。谢谢!我更清楚:)Kevin,值得注意的是,您的
布尔标志
除了表示新的构造函数方法签名之外,实际上并没有完成任何事情。如果您真的想要,您可以将值设置为
true
复制列表,将值设置为
false
仅在内部分配引用。