一、api已有的不可变类
概念:当创建了这个类的实例后,就不允许修改它的值了,类似于常量(const),即只允许别的程序读,不允许别的程序进行修改
所有基本类型的包装类都是不可变类,此外String也是不可变类
//不可变类
String s="hello";
System.out.println(s.hashCode());
s+=" world";
System.out.println(s.hashCode());
System.out.println(s);
//可变类
Person p1=new Person();
System.out.println(p1.hashCode());
p1.setAge(10);
System.out.println(p1.hashCode());
s+=“world”并没有改变s所指向的对象,此句代码运行后,s指向了另一个String对象,该对象的内容是“hello world”
二、创建不可变类
①类中所有成员变量被private所修饰
②类中没有写或者修改成员变量的方法,例如setxxxx,只提供构造函数,一次生成,永不改变
③确保类中所有方法不会被子类覆盖,可以通过把类定义成final或者类中方法定义成final来达到目的
解释:定义成final类,则不可被继承,方法自然不能被覆盖;定义final方法,子类可以使用该方法,但是不能被覆盖
④如果一个类成员不是不可变量,那么在成员初始化或者使用get方法获取该成员变量时,需要通过clone方法来保证类的不可变性
public class Person extends ArrayList //继承ArrayList原因:Object没有实现clone,只能找一个
已经实现clone方法的类
{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(int age){
this.age=age;
}
public class Woman {
private Person p;
public Woman(Person p){
this.p=(Person) p.clone(); //这里进行深度复制,解除引用关系
}
public void getage(){
System.out.println(p.getAge());
}
public static void main(String[] args) {
Person p=new Person(10);
Woman women=new Woman(p);
women.getage();
p.setAge(80);
women.getage();
}
}
需要注意的是:由于类不可变性,在创建对象时就需要初始化所有成员变量,因此最好提供一个带参数的构造函数来初始化这些变量