【问题标题】:Is a mutable object still constant可变对象是否仍然不变
【发布时间】:2014-09-03 12:09:53
【问题描述】:

如果我有一个对象,比如说

public class Person {

    private int age;

    public Person(int age) {
        this.age = age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
} 

public static final Person PERSON = new Person(12);

因为我仍然可以改变年龄,所以它不被认为是恒定的吗?

【问题讨论】:

标签: java constants


【解决方案1】:

因为我仍然可以改变年龄,所以它不被认为是恒定的吗?

PERSON 是“常量”,因为它总是指向 same Person 实例。然而,它所指向的Person 实例并不是恒定的,因为它可以被变异。这更像是一个术语问题。

【讨论】:

  • @ErikMadsen 同样,我认为这确实是一个没有有意义答案的术语问题。我稍作编辑以澄清我的意思。
【解决方案2】:

它是 final(constant) 的引用,但您仍然可以更新其状态(实例变量),但您不能将其分配给其他 Person 对象。

JLS - 4.12.4. final Variables 下更好解释

一旦分配了最终变量,它总是包含相同的值。

如果一个final变量持有一个对象的reference,那么对象的状态可能会被对象的操作改变,但变量总是指向同一个对象。

你不能说

person = new Person(20);

【讨论】:

  • 您试图展示的基元类型和引用类型之间的区别是什么?
  • 为什么在原始的情况下不能再次赋值,而在对象的情况下可以?
  • 基元 对象都是不可能的。
  • 您所说的“在原始情况下不可能再次赋值但对象可能”是什么意思?赋值不同于操纵其状态。
  • @Pshemo 删除了原语和字符串部分以避免混淆。
【解决方案3】:

把它想象成现实生活中的样子。您创建的 PERSON 是一个具体的人。您可以使用 PERSONuser2896769 或使用一些独特的 ID 对其进行标记。当你通过这个标签引用对象时,你总是引用同一个对象(因为它是最终的),但对象本身可以改变(就像现实中的人会变老,所以他们的年龄会改变)。

所以final 表示引用是常量,而不是对象本身是不可变。 如果您希望您的 PERSON 完全不改变,那么引用必须是 final,并且引用指向的对象必须是 immutable

当你写作时:

public static final Person PERSON = new Person(12);

这意味着从现在开始 PERSON 将引用新创建的 person 对象。 并不意味着 PERSON 新创建的 person 对象。再次 - 这意味着它引用(指向)对象。这样你就有一个对象的引用。而且这个引用是最终的,不变的,总是指向同一个对象。但是对象本身可以改变,只要它是可变的。

【讨论】:

    【解决方案4】:

    我认为 PERSON 是否为常量是语义问题,但它不被视为“常量”,而是最终对象引用。

    此外,我会为变量选择正常的小写命名。 this question 对此进行了很好的讨论。

    上述问题中的一个答案引用了 Effective Java, 2nd edition for the following criteria for a field is constant:

    常量字段是一个静态的最终字段,其值是不可变的。如果 静态最终字段具有原始类型或不可变引用 type (...),那么它就是一个常量字段。

    【讨论】:

      猜你喜欢
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-26
      相关资源
      最近更新 更多