如何写一个不可变类

本文由 ImportNew - 唐小娟 翻译自 Journaldev。欢迎加入Java小组。转载请参见文章末尾的要求。

   不可变的对象指的是一旦创建之后,它的状态就不能改变。String类就是个不可变类,它的对象一旦创建之后,值就不能被改变了。

   阅读更多: 为什么String类是不可变的

   不可变对象对于缓存是非常好的选择,因为你不需要担心它的值会被更改。不可变类的另外一个好处是它自身是线程安全的,你不需要考虑多线程环境下的线程安全问题。

   阅读更多: Java线程教程以及Java多线程面试问题

   Here I am providing a way to create immutable class via an example for better understanding.

下面是创建不可变类的方法,我也给出了代码,加深理解。

要创建不可变类,要实现下面几个步骤:

  1. 将类声明为final,所以它不能被继承
  2. 将所有的成员声明为私有的,这样就不允许直接访问这些成员
  3. 对变量不要提供setter方法
  4. 将所有可变的成员声明为final,这样只能对它们赋值一次
  5. 通过构造器初始化所有成员,进行深拷贝(deep copy)
  6. 在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝

为了理解第5和第6条,我将使用FinalClassExample来阐明。

import java.util.HashMap;
import java.util.Iterator;


/**
 * @Description 
 * @Author hzmoudaen
 * @Since 2014-5-11
 */


public final 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;
}

/** ------------------------------------------------------------1-------------------
* 访问可变对象 克隆
* @return
*/
@SuppressWarnings("unchecked")
public HashMap<String, String> getTestMap(){
return (HashMap<String, String>)testMap.clone();//返回对象的复制
}

/**------------------------------------------2--------------------------
* 访问可变对象 复制
* @return
*/
// public HashMap<String, String> getTestMap(){
// return testMap;//直接返回对象的引用
// }

/**-----------------------------------------3------------------------------
* 深复制
* @param i
* @param n
* @param hm
*/
public FinalClassExample(int i,String n,HashMap<String, String>hm){
System.out.println("Perfoming deep copy for object inititalization");
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;
}

/**---------------------------------------4------------------------------------
* 浅复制
* @param i
* @param n
* @param hm
*/
// public FinalClassExample(int i,String n,HashMap<String, String>hm){
// System.out.println("Perfoming shallow copy for object inititalization");
// this.id = i;
// this.name = n;
// this.testMap = hm;
// }

public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("1", "first");
map.put("2", "second");
String s = "original";
int i = 10;
FinalClassExample example = new FinalClassExample(i, s, map);
//下面看一个复制的域还是引用
System.out.println(s==example.getName());
System.out.println(map == example.getTestMap());
//打印example的值
System.out.println("example id="+example.getId());
System.out.println("example name="+example.getName());
System.out.println("example testmap = "+ example.getTestMap());

//改变局部变量的值
i = 20;
s ="modify";
map.put("3", "third");
//打印值
System.out.println("example id after local variable change ="+example.getId());
System.out.println("example name after local variable change ="+example.getName());
System.out.println("example testmap after local variable change = "+ example.getTestMap());

HashMap<String, String> hm = example.getTestMap();
hm.put("4", "new");
System.out.println("example testMap after changing variable from accessor methords:"+example.getTestMap());
}
}

输出:

Perfoming deep copy for object inititalization
true
false
example id=10
example name=original
example testmap = {2=second, 1=first}
example id after local variable change =10
example name after local variable change =original
example testmap after local variable change = {2=second, 1=first}
example testMap after changing variable from accessor methords:{2=second, 1=first}

   现在我们注释掉深拷贝的构造器,取消对浅拷贝构造器的注释。即注释掉代码-----1---和代码-------3----,打开代码------------2--------,---4---。输出:

Perfoming shallow copy for object inititalization
true
true
example id=10
example name=original
example testmap = {2=second, 1=first}
example id after local variable change =10
example name after local variable change =original
example testmap after local variable change = {3=third, 2=second, 1=first}
example testMap after changing variable from accessor methords:{3=third, 2=second, 1=first, 4=new}

   从输出可以看出,HashMap的值被更改了,因为构造器实现的是浅拷贝,而且在getter方法中返回的是原本对象的引用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值