如何在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中。