为什么 Java 中的包装器 class 的行为不像引用类型?

Why wrapper class in Java doesn't behave like a reference type?

我很难理解为什么 Java 中的包装器 class 的行为不像引用类型。 示例:

Integer one = 10;
Integer two = one;
one = 20;
System.out.println(one);
System.out.println(two);

输出将是:

20

10

我认为 two 将是 20,就像在我创建自己的 class 的示例中一样:

class OwnInteger {
        private int integer;

        public OwnInteger(int integer) {
            this.integer = integer;
        }

        public int getInteger() {
            return integer;
        }

        public void setInteger(int integer) {
            this.integer = integer;
        }
    }

    OwnInteger one = new OwnInteger(10);
    OwnInteger two = one;
    one.setInteger(20);
    System.out.println(one.getInteger());
    System.out.println(two.getInteger());

那么问题来了,Integer wrapper class 有什么特别之处吗?为什么它的行为与我在示例中所示的一样?

I thought that two will be 20...

不,当你这样做的时候

Integer two = one;
one = 20;

您实际上是在为变量 one 分配一个新对象,而变量 two 将不会因这些更改而更新...

到你的 class OwnInteger

OwnInteger one = new OwnInteger(10);
OwnInteger two = one;
one.setInteger(20);

它们如您所愿,因为 onetwo 指向相同的引用..

代码 A 将等同于

OwnInteger one = new OwnInteger(10);
OwnInteger two = one;
one = new OwnInteger(20); //one.setInteger(20);

这正是引用类型的行为。在您的示例中, two 在赋值后引用与 one 相同的对象。但是,重新分配 one 新对象对 two 没有影响,这就是您看到的行为。

您也会看到与其他参考对象相同的行为,例如

StringBuilder one = new StringBuilder("10");
StringBuilder two = one;
one = new StringBuilder("20");
// two still references StringBuilder with "10"

为了使引用 class 在更改一个对象时同时更改另一个对象时表现出行为,class 需要 mutable,例如OwnInteger class 在您的代码中, 代码需要更改对象,而不是重新分配它。包装器 classes,例如 Integer,是不可变的,因此您不会遇到这种行为。

one = 20;

using "boxing",实际上等同于:

one = Integer.valueOf(20);

在您的情况下,valueOf 方法创建一个新对象和 return 该新创建对象的引用,因为之前不存在于缓存中。

对于您自己的 class onetwo 两个引用变量都指向同一个对象。

到目前为止,其他答案都至少部分错误。您看到的效果与自动装箱或可变性无关。像第一步那样更改指针和像第二步那样通过指针更改对象是完全不同的事情。更改指针将其指向不同的对象。您没有更改两个指针,因此它们指向不同的对象。无论可变性或装箱转换如何,都会发生这种情况。