今天我们将学习如何在java中创建不变的类。不可变对象是在初始化之后状态不变的实例。例如,String是一个不可变类,一旦实例化,它的值不会改变。
不可改变的类对于缓存的目的是有益的,因为你不需要担心价值的变化。不可变类的其他好处是它本质上是线程安全的,所以在多线程环境的情况下,您不需要担心线程安全。
在这里,我提供了一种通过一个例子来创建Java中不可变类的方法,以便更好地理解。
要在java中创建不可变类,您必须执行以下步骤。
要了解第4点和第5点,我们来运行Final类,其效果很好,实例化后值不会被更改。
FinalClassExample.java
import java.util.HashMap;
import java.util.Iterator;
/**
* <p></p>
*
* @author 三产
* @version 1.0
* @date 2017-03-24
* @QQGroup 213732117
* @website http://www.coderknock.com
* @copyright Copyright 2017 拿客 coderknock.com All rights reserved.
* @since JDK 1.8
*/
public class FinalClassExample {
private final int id;
private final String name;
private final HashMap<String,String> testMap;
public int getId() {
return id;
}
public String getName() {
return name;
}
/**
* 可变对象的访问器函数
*/
public HashMap<String, String> getTestMap() {
return (HashMap<String, String>) testMap.clone();
}
/**
* 构造函数 执行深层复制
* @param i
* @param n
* @param hm
*/
public FinalClassExample(int i, String n, HashMap<String,String> hm){
System.out.println("执行 深复制 对象初始化");
this.id=i;
this.name=n;
HashMap<String,String> tempMap=new HashMap<String,String>();
String key;
Iterator<String> it = hm.keySet().iterator();
while(it.hasNext()){
key=it.next();
tempMap.put(key, hm.get(key));
}
this.testMap=tempMap;
}
/**
* 测试 浅复制 的后果以及如何避免使用 深复制 创建不可变类
* @param args
*/
public static void main(String[] args) {
HashMap<String, String> h1 = new HashMap<String,String>();
h1.put("1", "first");
h1.put("2", "second");
String s = "original";
int i=10;
FinalClassExample ce = new FinalClassExample(i,s,h1);
//让我们看看它是按字段还是引用复制。
System.out.println(s==ce.getName());
System.out.println(h1 == ce.getTestMap());
//print the ce values
System.out.println("ce id:"+ce.getId());
System.out.println("ce name:"+ce.getName());
System.out.println("ce testMap:"+ce.getTestMap());
//修改本地变量的值
i=20;
s="modified";
h1.put("3", "third");
System.out.println("ce id after local variable change:"+ce.getId());
System.out.println("ce name after local variable change:"+ce.getName());
System.out.println("ce testMap after local variable change:"+ce.getTestMap());
HashMap<String, String> hmTest = ce.getTestMap();
hmTest.put("4", "new");
System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap());
}
}
输出如下:
执行 深复制 对象初始化
true
false
ce id:10
ce name:original
ce testMap:{1=first, 2=second}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{1=first, 2=second}
ce testMap after changing variable from accessor methods:{1=first, 2=second}
修改构造函数为浅复制,输出如下:
执行 浅复制 对象初始化
true
false
ce id:10
ce name:original
ce testMap:{1=first, 2=second}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{1=first, 2=second, 3=third}
ce testMap after changing variable from accessor methods:{1=first, 2=second, 3=third}
对比两次输出可以看出,HashMap 值由于构造函数中的浅复制而改变,并提供对getter函数中原始对象的直接引用。