immutabletable java_如何在Java中创建Immutable的类

首先,我们需要明白什么是Immutable的类。顾名思义,就是在对象创建后,它的状态不能改变。你首先也许会想到final这个关键字,因为它会使被修饰者要么不能被继承(修饰类),要么不能被重新赋值(修饰字段)。下面我们来看一个简单的例子:

final class ImmutableClass_1 {private final int i = 0;private final double j = 1;int getI() {return i;}double getJ() {return j;}}

这个类被final修饰,意味着它不能被继承,去除了子类修改状态的可能。字段i和j都被什么味final因为这它不能被重新赋值,所以它们都是不能改变的。最后这个类中没有任何的构造函数或者setter方法能对其中的字段做出改变。综上所述,这个类是一个不可变类。

下面让我们来看一个稍微复杂一些的例子:

final class MutableClass_1 {private final int i = 0;private final List stringList = new ArrayList();int getI() {return i;}List getStringList() {return stringList;}}

这个类和上面那个类很相似,类被final修饰,字段也被final修饰,但是它却并非immutable,问题出在stringList上。我们都知道在创建对象的时候,对象名只是一个指向真正对象的引用,我们可以通过这个引用去修改被指向的对象。这里的getStringList方法返回了这个对象的引用,于是这个对象就会有2个引用指向它,所以客户端可以通过下面这段代码来改变对象:

public class test {public static void main(String[] args) {MutableClass_1 mutableClass_1 = new MutableClass_1();System.out.println(mutableClass_1.getStringList()); // print '[]'mutableClass_1.getStringList().add("a new string");System.out.println(mutableClass_1.getStringList()); // print 'a new string'}}

我们看到mutableClass_1这个对象中的字段被改变了,所以它不是immutable的。如果想要让上面这个MutableClass_1变成不可变的,就需要用到Java中的深拷贝和浅拷贝了。代码如下:

final class ImmutableClass_2 {private final int i = 0;private final List original = new ArrayList();int getI() {return i;}List getStringList() {List copy = new ArrayList();for (String s : original) {copy.add(s);}return copy;}}

我在返回这个list的时候使用了深拷贝,返回了一个与老的list值完全一样的一个新的list。这样,在客户端调用的时候,指向的是另一个list了。所以下面这段代码就不能修改这个类了。

public class test {public static void main(String[] args) {ImmutableClass_2 mutableClass_2 = new ImmutableClass_2();System.out.println(mutableClass_2.getStringList()); // print '[]'mutableClass_2.getStringList().add("a new string");System.out.println(mutableClass_2.getStringList()); // print '[]'}}

其实在Java中有很多默认的类都是immutable的,例如String,Integer等。这就意味着,当你在使用String的一些方法的时候,其实它返回的是另一个对象,原对象并没有改变。比如:

public class test {public static void main(String[] args) {String a = "AbC";String b = a.toLowerCase();System.out.println(a); // print 'AbC'System.out.println(b); // print 'abc'}}

总结起来,如果要创建一个‘不可变’类,需要遵守下面几条:

1、Class应该定义成final,避免被继承

2、所有的成员变量应该被定义成final

3、尽量不要暴露mutable的字段(例如list),如果要暴露,使用深拷贝或浅拷贝

4、不要提供可以改变类状态(成员变量)的方法(get 方法不要把类里的成员变量让外部客服端引用,当需要访问成员变量时,返回成员变量的copy)

5、构造函数不要引用外部可变对象。如果需要引用外部可以变量,应该在构造函数里进行defensive copy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值