如何在Java中创建不可变类
时间:2020-02-23 14:41:28 来源:igfitidea点击:
在本教程中,我们将看到如何在Java中创建不可变类。
不可变类是程序,其状态在创建后无法更改。
示例:String是不可变类的最佳示例。
创建字符串后,我们无法更改它。
不可阻挡的类非常简单,它只有一个州。
构造函数仔细执行了不可改变的程序。
不变的程序是线程安全的。
这是不可变类的最大优势,我们无需对不可变量的同步应用同步。
在将Offutable类放在HashMap中的对象或者其可用于缓存目的,因此不可变类可能是有用的,因为它的值不会改变。
Immutable objects are by default thread safe.
创建不可变类的步骤:
- 让你的类决赛:如果你做你的类决赛,没有程序将能够扩展它,因此将无法覆盖此类的方法。
- 使用私有和最终声明所有实例变量:如果我们使实例变量私有,则不包含外部类将能够访问实例变量,如果我们使它们最终,则无法更改它。
- 对Setter方法说否:不要为任何实例变量创建Setter方法,因此不会有明确的方法来更改实例变量的状态。
- 初始化构造函数中的所有变量:我们可以初始化构造函数中的变量。使用可变对象时需要特别小心。在模仿对象的情况下,我们需要做深刻的副本。
- 从getter方法返回时执行可变对象的克隆:如果从getter方法返回对象的克隆,则不会返回原始对象,因此原始对象将保持完整。我将在本教程的后期部分解释这一点。
让我们了解一个非常简单的例子:让我们创建一个名为国家/地区的简单类。
Java。
public final class Country{
private final String countryName;
private final ArrayList listOfStates;
public Country(String countryName,ArrayList listOfStates) {
super();
this.countryName = countryName;
this.listOfStates=listOfStates;
}
public String getCountryName() {
return countryName;
}
public ArrayList getListOfStates() {
return listOfStates;
}
public static void main(String args[])
{
ArrayList listOfStates=new ArrayList();
listOfStates.add("Madhya Pradesh");
listOfStates.add("Maharastra");
listOfStates.add("Gujrat");
Country country=new Country("Netherlands",listOfStates);
System.out.println("Country : "+country.getCountryName());
System.out.println("List of states : "+country.getListOfStates());
//It will be added to the list because we did not use clone in getListOfStates
country.getListOfStates().add("Kerala");
//It will be added to the list because we did not use deep copy in constructor
listOfStates.add("Rajasthan");
System.out.println("Updated List of states : "+country.getListOfStates());
}
}
运行程序时,我们将得到以下输出:
Country : Netherlands List of states : [Madhya Pradesh, Maharastra, Gujrat] Updated List of states : [Madhya Pradesh, Maharastra, Gujrat, Kerala, Rajasthan]
上面的程序不是不可变的。
它有两个原因:
- 我们没有在getListofstates()方法中使用克隆,因此我们能够将"kerala"添加到listofstates。
- 我们没有为listofstates做好副本,因此我们能够将"Rajasthan"添加到列表中。
让我们在getListofstates()方法中使用克隆,看看差异,只需将getListOfStates()更改为以下代码:
public ArrayList getListOfStates() {
return (ArrayList) listOfStates.clone();
}
在进行上述更改后运行程序,我们将得到以下输出:
Country : Netherlands List of states : [Madhya Pradesh, Maharastra, Gujrat] Updated List of states : [Madhya Pradesh, Maharastra, Gujrat, Rajasthan]
如果我们注意到,"kerala"未添加到列表中,因为我们在getListofstates()方法中返回Listofstates的克隆,因此将"kerala"添加到country.getlistofstates()不会影响原始列表。
我们现在是一步到不可变的程序。
允许更改构造函数以使ListOfStates对象的深度副本。
public Country(String countryName, ArrayList listOfStates) {
super();
this.countryName = countryName;
ArrayList tempList = new ArrayList();
for (int i = 0; i < listOfStates.size(); i++) {
tempList.add(listOfStates.get(i));
}
this.listOfStates = tempList;
}
让我们检查在上述更改后我们创建的最终类。
package org.igi.theitroad.bean;
import java.util.ArrayList;
public final class Country {
//declared private final instance variable
private final String countryName;
//Mutable object
private final ArrayList listOfStates;
public Country(String countryName, ArrayList listOfStates) {
super();
this.countryName = countryName;
//Creating deep copy for mutable object
ArrayList tempList = new ArrayList();
for (int i = 0; i < listOfStates.size(); i++) {
tempList.add(listOfStates.get(i));
}
this.listOfStates = tempList;
}
public String getCountryName() {
//Do not need to do cloning as it is immutable object
return countryName;
}
public ArrayList getListOfStates() {
//Returning cloned object
return (ArrayList) listOfStates.clone();
}
public static void main(String args[]) {
ArrayList listOfStates = new ArrayList();
listOfStates.add("Madhya Pradesh");
listOfStates.add("Maharastra");
listOfStates.add("Gujrat");
String countryName="Netherlands";
Country country = new Country(countryName, listOfStates);
System.out.println("Country : " + country.getCountryName());
//Lets try to change local variable countryName
countryName="China";
System.out.println("Updated Country : " + country.getCountryName());
System.out.println("List of states : " + country.getListOfStates());
//It will not be added to the list because we are using clone in
//getListOfStates
country.getListOfStates().add("Kerala");
//It will not be added to the list because we are using deep copy in
//constructor
listOfStates.add("Rajasthan");
System.out.println("Updated List of states : " + country.getListOfStates());
}
}
运行上面的程序时,我们将得到以下输出:
Country : Netherlands Updated Country : Netherlands List of states : [Madhya Pradesh, Maharastra, Gujrat] Updated List of states : [Madhya Pradesh, Maharastra, Gujrat]
国家类现在是不可变的程序。
正如我们所看到的,我们正在为ListOfStates做深刻的副本,因此不会将"Rajasthan"添加到Listofstates中。

