0

我在一个类中有一个 Long 对象,我给它一个值,然后我将它传递给另一个类的构造函数,在那里它被改变了。为什么在第一个对象中看不到更改?

编码:

public class ClassA {
    private Long t;

    public ClassA() {
        t = new Long(10);
        System.out.println(t); // prints 10
        new ClassB(t); // it is modified (see ClassB)
        System.out.println(t); // prints 10 again
    }

    public static void main(String[] args) {
        new ClassA();
    }
}

class ClassB {
    private Long p;

    public ClassB(Long p) {
        this.p = p;
        this.p = this.p + 1;
        System.out.println(this.p); // prints 11
    }
}

输出为: 10 11 10 Long 变量在 ClassA 中初始化。然后我将它传递给 ClassB,对其进行修改,显然这些更改在第一堂课中不可见。为什么?

4

6 回答 6

6

这是因为Long类是不可变的;一旦创建了一个实例,它就永远不会改变。

在这一行:

this.p = this.p + 1;

你正在做的是创建一个 Long对象。不可变类的其他示例包括原始数字类型(ByteShort)和String.

没有帮助的是它使+操作员不直观。真正没有帮助的是该语言允许所有+这些不可变类。

上一行中发生的事情可以写成(尽管我怀疑它在字节码中发生的方式不同):

long tmp = this.p.longValue();
tmp += 1;
this.p = new Long(tmp);

您还可以通过在 class 中标记pas来验证不变性,这意味着引用永远不会改变;由于您尝试修改 reference 将引发编译错误。finalB pthis.p = this.p + 1p

于 2013-06-15T12:33:06.580 回答
2

此行this.p = this.p + 1;不修改 p,它通过Long添加两个值创建一个新的p1然后设置this.p为对这个新的引用Long。类的对象Long没有 mutator 方法,因此它们永远不会改变(在 Class B 内this.p没有改变,this.p成为对Long 的引用)

所以行为实际上是

this.p=p;
Long newLong=this.p + 1;
this.p=newLong;

你想象的是

this.p=p
this.p.imaginaryAddLocal(1);

这会影响原来的 p,但是这个方法当然imaginaryAllLocal不存在,因为 Long 类的对象是不可变的

于 2013-06-15T12:33:21.630 回答
0

首先,Long是不可变的。这意味着您不能更改在构造函数中设置的值(注意没有set方法)。

当你这样做

this.p = this.p + 1;

Java 可以。

1)自动转换this.p为其长值(原始)

2) 算术运算

3) 将结果自动转换回一个新的、不同的 Long 并将引用分配给this.p

t一直指向原始Long对象。

在 Java 中,您可以通过对象的属性(不可建议,您应该制作它们private)或其方法来修改对象。一个+(或其他操作员)永远不会改变一个对象的状态(尽管它可能会创建一个新的,在唯一的情况下myString1 + myString2

于 2013-06-15T12:34:13.640 回答
0

1-您只是在修改 B 类的 p 成员
2-Java 中的所有内容都是通过值(而不是通过引用)传递的

于 2013-06-15T12:35:17.350 回答
-1

该类Long是不可变的,因此您不能通过在被调用函数中修改它来传回该值。在您ClassB的副本中创建并且原始值永远不会改变。

如果您希望调用者看到更改的值,则必须将其作为返回值传回。

其他原始包装器和 String 也是如此。

于 2013-06-15T12:33:21.043 回答
-2

因为 Java 使用传递引用。这意味着它传递变量的副本,而不是对“原始”变量的引用。

例如,在 C++ 中,您可以这样做:

void change_var(int &x)
{
    x = 2;
}

int x = 10;
change_var(x);
std::cout << x << std::endl;

这将打印,因为正在传递2对变量的引用,而不是副本。x

于 2013-06-15T12:33:11.633 回答