[英]Make immutable Java object
My goal is to make a Java object immutable.我的目标是使 Java 对象不可变。 I have a class
Student
.我有一个班级
Student
。 I coded it in the following way to achieve immutability:我以以下方式对其进行编码以实现不变性:
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 Student
class?我的问题是,实现
Student
类不变性的最佳方法是什么?
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.
不可变类本质上是线程安全的,有效的不可变类只有在安全发布时才是线程安全的。
There are few things that you must consider for making an immutable class:要创建一个不可变的类,您必须考虑以下几点:
final
- You already havefinal
- 你已经有了private
and final
- Make appropriate changes in your codeprivate
和final
字段 - 在代码中进行适当更改List
, or Date
, making them final
won't suffice.List
或Date
,将它们设为final
不够的。 You should return a defensive copy from their getters
, so that their state isn't mutated by calling methods.getters
返回一个防御性副本,这样他们的状态就不会因为调用方法而改变。 For the 4th point, say you have a Date
field 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.
但是,把这个问题分开,你应该再次考虑你的类设计,一旦你发现自己陷入了制作深度防御性副本的要求。
How do you make a mutable object immutable?
如何使可变对象不可变?
Why do we create immutable objects?
我们为什么要创建不可变对象?
Immutable objects are simply objects whose state (the object's data) cannot change after construction.不可变对象只是其状态(对象的数据)在构造后无法更改的对象。
With final
keyword:使用
final
关键字:
private final String name;
private final String age;
Making variables private and no setter methods will work for primitive data types.将变量设为私有且没有 setter 方法将适用于原始数据类型。 If my class has any collection of objects?
如果我的班级有任何对象集合?
To making any class immutable with collection object?使用集合对象使任何类不可变?
Write your own collection object with extends collection class and follow the private variables and no setter methods.使用 extends 集合类编写自己的集合对象,并遵循私有变量而不是 setter 方法。 or return clone object of your collection object.
或返回您的集合对象的克隆对象。
public final class Student {
private StudentList names;//Which is extended from arraylist
public Student() {
names = DAO.getNamesList()//Which will return All Student names from Database its upto you how you want to implement.
}
public StudentList getStudentList(){
return names;//you need to implement your own methods in StudentList class to iterate your arraylist; or you can return Enumeration object.
}
public Enumeration getStudentNamesIterator(
Enumeration e = Collections.enumeration(names);
return e;
}
public class StudentList extends ArrayList {
}
This is fine but I would make the fields final
as well.这很好,但我也会将这些字段设为
final
。
Also I would make the age an int
or double
rather than a String.此外,我会将年龄
int
或double
而不是 String。
Expanding on the answer a bit.稍微扩展一下答案。
final
is not the same as Immutable
but you can use final
to make certain things immutable if you use it in certain ways. final
与Immutable
但如果您以某种方式使用它,您可以使用final
使某些事物不可变。
Certain types are immutable, in that they represent unchanging values rather than objects of changeable state.某些类型是不可变的,因为它们表示不变的值而不是状态可变的对象。 Strings, numbers, etc are immutable.
字符串、数字等是不可变的。 At the end, usually our objects boil down to data structures eventually referencing immutable values, but we change the data structures by assigning new values to the same field names.
最后,通常我们的对象归结为最终引用不可变值的数据结构,但我们通过将新值分配给相同的字段名称来更改数据结构。
So to make something truly immutable you need to make sure that final is used all the way down, until you reach every field reaching every value at the base of your composition tree.因此,要使某些东西真正不可变,您需要确保一直使用 final,直到到达每个字段,并达到组合树底部的每个值。 Otherwise something could change out from under your the object and it isn't really fully immutable.
否则,某些东西可能会从您的对象下方发生变化,并且它并不是完全不可变的。
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:要使对象不可变,您必须执行以下步骤:
It is too late to answer but may be it help other peoples who have this question.现在回答为时已晚,但可能会帮助其他有此问题的人。
I think this link help more Read more: http://javarevisited.blogspot.com/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html#ixzz40VDQDDL1我认为这个链接帮助更多阅读更多: http : //javarevisited.blogspot.com/2013/03/how-to-create-immutable-class-object-java-example-tutorial.html#ixzz40VDQDDL1
It already is immutable -- you can't change the contents once you initialize it, since you haven't made setters.它已经是不可变的——一旦你初始化它,你就不能改变它的内容,因为你还没有创建 setter。 You might add final keywords to the variables.
您可以将 final 关键字添加到变量中。
将所有变量设置为final
并在设置某个字段时,使其返回对具有新设置值的新Student
对象的引用,如String
。
您只需遵循本示例中显示的指南(谷歌中的第一个结果): http : //www.javapractices.com/topic/TopicAction.do? Id= 29
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.这里有一些规则,这有助于在 Java 中使类不可变: 1. 不可变对象的状态在构造后不能修改,任何修改都应产生新的不可变对象。 2. All fields of Immutable class should be final.
2. Immutable 类的所有字段都应该是最终的。 3. Object must be properly constructed ie object reference must not leak during construction process.
3. 对象必须正确构造,即对象引用在构造过程中不能泄漏。 4. Object should be final in order to restrict sub-class for altering immutability of parent class.
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
According to Strategy for Defining Immutable Objects根据定义不可变对象的策略
Don't provide " setter
" methods — methods that modify fields or objects referred to by fields.不要提供“
setter
”方法——修改字段或字段引用的对象的方法。
Make all fields final
and private
.将所有字段设为
final
和private
。
Don't allow subclasses to override methods.不允许子类覆盖方法。 The simplest way to do this is to declare the class as
final
.最简单的方法是将类声明为
final
。
a. a. A more sophisticated approach is to make the
constructor
private and construct instances in factory methods.更复杂的方法是使
constructor
私有并在工厂方法中构造实例。
If the instance fields include references to mutable objects, don't allow those objects to be changed:如果实例字段包含对可变对象的引用,则不允许更改这些对象:
a. a. Don't provide methods that modify the mutable objects.
不要提供修改可变对象的方法。
b.湾Don't share references to the mutable objects.
不要共享对可变对象的引用。 Never store references to external, mutable objects passed to the constructor;
永远不要存储对传递给构造函数的外部可变对象的引用; if necessary, create copies, and store references to the copies.
如有必要,创建副本并存储对副本的引用。 Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
同样,必要时创建内部可变对象的副本,以避免在方法中返回原始对象。
You can use JEP 395: Records feature, introduced as part of Java SE 16, to create an immutable class in a succinct manner.您可以使用JEP 395:记录功能(作为 Java SE 16 的一部分引入)以简洁的方式创建不可变类。
If you have already gone through the above link, you must have figured out that you can do it simply as如果你已经通过上面的链接,你一定已经想出你可以简单地做到这一点
record Student(String name, String age) { }
What you get in turn are:你依次得到的是:
final class Student
. final class Student
。Student(String name, String age)
.Student(String name, String age)
相同的规范构造函数。private final
fields, name
and age
and their corresponding public
accessor method with the same name and return type. private final
字段、 name
和age
以及它们对应的具有相同名称和返回类型的public
访问器方法。equals
, hashCode
and toString
methods.equals
、 hashCode
和toString
方法。 Student.java学生.java
record Student(String name, String age) { }
Main.java主程序
class Main{
public static void main(String[] args) {
Student s1 = new Student("Bharat", "10 Years");
Student s2 = new Student("Arvind", "10 Years");
System.out.println(s1);
System.out.println(s1.equals(s2));
System.out.println(s1.age().equals(s2.age()));
}
}
Output:输出:
Student[name=Bharat, age=10 Years]
false
true
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
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.