制作不可变的 Java 对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18194139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:11:22  来源:igfitidea点击:

Make immutable Java object

javaimmutability

提问by Ruchira Gayan Ranaweera

My goal is to make a Java object immutable. I have a class Student. I coded it in the following way to achieve immutability:

我的目标是使 Java 对象不可变。我有一堂课Student。我以以下方式对其进行编码以实现不变性:

public final class Student {

private String name;
private String age;

public Student(String name, String age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}

public String getAge() {
    return age;
}

}

My question is, what is the best way to achieve immutability for the Studentclass?

我的问题是,实现Student类的不变性的最佳方法是什么?

采纳答案by assylias

Your class is not immutable strictly speaking, it is only effectively immutable. To make it immutable, you need to use final:

严格来说,您的类不是一成不变的,它只是有效地不可变。要使其不可变,您需要使用final

private final String name;
private final String age;

Although the difference might seem subtle, it can make a significant difference in a multi-threaded context. An immutable class is inherently thread-safe, an effectively immutable class is thread safe only if it is safely published.

尽管差异可能看起来很微妙,但它可以在多线程上下文中产生显着差异。不可变类本质上是线程安全的,有效的不可变类只有在安全发布时才是线程安全的。

回答by Adam Stelmaszczyk

With finalkeyword:

final关键字:

private final String name;
private final String age;

回答by Peter Lawrey

This is fine but I would make the fields finalas well.

这很好,但我也会制作字段final

Also I would make the age an intor doublerather than a String.

此外,我会让年龄成为一个intdouble而不是一个字符串。

回答by Nick C

It already is immutable -- you can't change the contents once you initialize it, since you haven't made setters. You might add final keywords to the variables.

它已经是不可变的——一旦你初始化它,你就不能改变它的内容,因为你还没有创建 setter。您可以将 final 关键字添加到变量中。

回答by ps-aux

Making all variables as finaland when setting some field, making it return the reference to the new Studentobject with the newly set value like in String.

final在设置某个字段时将所有变量设置为,使其返回对Student具有新设置值的新对象的引用,例如 in String

回答by JPetric

You can just follow guidelines shown in this example (first result in google): http://www.javapractices.com/topic/TopicAction.do?Id=29

您只需遵循本示例中显示的指南(谷歌中的第一个结果):http: //www.javapractices.com/topic/TopicAction.do?Id= 29

回答by Rohit Jain

There are few things that you must consider for making an immutable class:

要创建一个不可变的类,您必须考虑以下几点:

  • Make your class final- You already have
  • Make all the fields privateand final- Make appropriate changes in your code
  • Don't provide any methods that change the state of your instance
  • If you have mutable fields in your class, like List, or Date, making them finalwon't suffice. You should return a defensive copy from their getters, so that their state isn't mutated by calling methods.
  • 让你的班级final- 你已经有了
  • 制作所有字段privatefinal- 在您的代码中进行适当的更改
  • 不要提供任何改变实例状态的方法
  • 如果您的类中有可变字段,例如List, 或Date,那么仅使用它们是final不够的。你应该从他们的 返回一个防御性副本getters,这样他们的状态就不会因为调用方法而改变。

For the 4th point, say you have a Datefield in your class, then the getter for that field should look like:

对于第 4 点,假设您Date的班级中有一个字段,那么该字段的 getter 应如下所示:

public Date getDate() {
    return new Date(this.date.getTime());
}

Making a defensive copy can become a headache, when your mutable field itself comprises of some mutable field, and that in turn can contain some other mutable field. In that case, you would need to make copy of each of them iteratively. We name this iterative copy of mutable fields as Deep Copy.

当您的可变字段本身包含一些可变字段,而该可变字段又可以包含其他一些可变字段时,制作防御性副本可能会令人头疼。在这种情况下,您需要迭代地复制它们中的每一个。我们将这个可变字段的迭代副本命名为Deep Copy

Implementing deep copy by yourself may be cumbersome. But,keeping that issue apart, you should consider your class design again, once you see yourself falling into such requirement of making deep defensive copy.

自己实现深拷贝可能很麻烦。但是,把这个问题分开,你应该再次考虑你的类设计,一旦你发现自己陷入了制作深度防御性副本的要求。

回答by Eldar Agalarov

Your example is already immutable object, because fields in Student class can only set on instance initialization.

您的示例已经是不可变对象,因为 Student 类中的字段只能在实例初始化时设置。

To make object immutable, You must do these steps:

要使对象不可变,您必须执行以下步骤:

  1. Don't use any methods, which can change fields of your class. For example don't use Setters.
  2. Avoid to use public non-final fields. If your fields is public then you must declare them as final and initialize them in constructor or directly in the declaration line.
  1. 不要使用任何可以更改类的字段的方法。例如,不要使用 Setter。
  2. 避免使用公共非最终字段。如果您的字段是公共的,那么您必须将它们声明为 final 并在构造函数中或直接在声明行中初始化它们。

回答by Vijay Bhatt

Here are few rules, which helps to make a class immutable in Java : 1. State of immutable object can not be modified after construction, any modification should result in new immutable object. 2. All fields of Immutable class should be final. 3. Object must be properly constructed i.e. object reference must not leak during construction process. 4. Object should be final in order to restrict sub-class for altering immutability of parent class.

这里有一些规则,这有助于在 Java 中使类不可变: 1. 不可变对象的状态在构造后不能修改,任何修改都应产生新的不可变对象。2. Immutable 类的所有字段都应该是 final 的。3. 对象必须正确构造,即对象引用在构造过程中不能泄漏。4.对象应该是最终的,以限制子类改变父类的不变性。

Example:

例子:

public final class Contacts {

private final String name;
private final String mobile;

public Contacts(String name, String mobile) {
    this.name = name;
    this.mobile = mobile;
}

public String getName(){
    return name;
}

public String getMobile(){
    return mobile;
}

}

}

Refer this link : http://javarevisited.blogspot.in/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html

请参阅此链接:http: //javarevisited.blogspot.in/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html

回答by suneelkumar

Make the class or variable as final that's more than enough

将类或变量设为 final 就足够了

Public final class constants
{
  private final String name;
  private final String mobile;

  // code
}