不可变类(immutable class)是指当创建了这个类的实例后,就不允许修改它的值了。也就是说,一个对象一旦被创建出来,在其整个生命周期中,它的成员变量就不能被修改了。它有点类似于常量(const),即只允许别的程序读,不允许别的程序进行修改。
在Java类库中,所有基本类型的包装类都是不可变类,例如Integer、Float等。此外,String也是不可变类。可能有人会有疑问,既然String是不可变类,为什么还可以写出如下代码来修改String类型的值呢?
public class Test{
public static void main(String[] args){
String s = "Hello";
s += " world";
System.out.println(s);
}
}
程序运行结果是:
Hello world
表面上看,好像是修改String类型对象s的值。其实不是,String s = “Hello” 语句声明了一个可以指向String类型的引用,这个引用的名字为s,它指向了一个字符串常量“Hello”。s+=“world”并没有改变s所指向的对象(由于“Hello”是String类型的对象,而String又是不可变量),这句代码运行后,s指向了另外一个String类型的对象,该对象的内容为“Hello world”。原来的那个字符串常量“Hello”还存在于内存中,并没有被改变。
下面介绍一下如何创建一个不可变类。通常来讲,要创建一个不可变类需要遵循下面4条基本原则:
1、类中所有成员变量被private所修饰。
2、类中没有写或者修改成员变量的方法,例如set**,只提供构造方法,一次生成,永不改变。
3、确保类中所有方法不会被子类覆盖,可以通过把类定义为final或者把类中的方法定义为final来达到这个目的。
4、如果有必要,可以使用覆盖Object类的equals()方法和hashCode()方法。在equals()方法中,根据对象的属性值来比较两个对象是否相等,并且保证用equals()方法判断为相等的两个对象的hashCode()方法返回值也相等,这可以保证这些对象能被正确地放到HashMap或者HashSet集合中。
除此之外,还有一些小的注意事项:由于类的不可变性,在创建对象时就需要初始化所有的成员变量,因此最好提供一个带参数的构造函数来初始化这些成员变量。