【Java学习笔记】如何定义Java中的不可变类
2017-11-01 23:35
267 查看
Java中的不可变类指的是该类的实例创建后,实例中的实例变量是不可改变的。Java提供的8个包装类以及java.lang.String类都是不可变类。
下面的程序试图创建一个不可变类Person,但是由于Person包含一个引用类型的成员变量,且这个引用类是可变类,所以导致Person类也变成了可变类。
public class Name {
private String firstName;
private String lastName;
public Name() {}
public Name(String firstName,String lastName) {
this.firstName=firstName;
this.lastName=lastName;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName=firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName=lastName;
}
}
public class Person {
private final Name name;
public Person(Name name) {
this.name=name;
}
public Name getName() {
return this.name;
}
public static void main(String[] args) {
Name n=new Name("悟空","孙");
Person p=new Person(n);
System.out.println(p.getName().getFirstName());
n.setFirstName("八戒");
System.out.println(p.getName().getFirstName());
}
}
运行程序,输出:
悟空八戒
可以看到,main函数中定义Person类的对象p时,使用了Name型引用变量n来初始化它。而后面程序将n的FirstName作了修改,同时,这引起了了Person类实例p内的实例变量发生了改变,于是Person类便也不再是不变类了。
为了保护Person类的不可变性,这就要求我们不能够通过改变Person对象内的引用类型变量n的内容来改变Person对象。只要让程序无法访问到可变的name,这样也就无法使Person对象的内的成员变量发生改变,同时保持了Person类的不变性。将程序作如下修改:
public class Person {
private final Name name;
public Person(Name name) {
//设置name实例变量为临时创建的Name对象,该对象的FirstName和LastName与
//传入的name参数的FirstName和LastName相同
this.name=new Name(name.getFirstName(),name.getLastName());
}
public Name getName() {
//返回一个匿名对象,该对象的FirstName与LastName与
//该对象里的name的FirstName和LastName相同
return new Name(name.getFirstName(),name.getLastName());
}
public static void main(String[] args) {
Name n=new Name("悟空","孙");
Person p=new Person(n);
System.out.println(p.getName().getFirstName());
n.setFirstName("八戒");
System.out.println(p.getName().getFirstName());
}
}
运行程序,输出:悟空悟空
可以说明,改变Name型引用变量n内的值没有对Person类对象造成影响,从而保护了Person类的不可变性。以上就是Java中不可变类定义时要注意的一些小问题,在需要用到可变对象对不可变类的对象进行初始化时,可以选择创建参数与可变对象相同的临时对象对不可变量进行初始化,这样在可变对象内容发生改变时,不会影响到不可变类的对象实例变量的改变。
下面的程序试图创建一个不可变类Person,但是由于Person包含一个引用类型的成员变量,且这个引用类是可变类,所以导致Person类也变成了可变类。
public class Name {
private String firstName;
private String lastName;
public Name() {}
public Name(String firstName,String lastName) {
this.firstName=firstName;
this.lastName=lastName;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName=firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName=lastName;
}
}
public class Person {
private final Name name;
public Person(Name name) {
this.name=name;
}
public Name getName() {
return this.name;
}
public static void main(String[] args) {
Name n=new Name("悟空","孙");
Person p=new Person(n);
System.out.println(p.getName().getFirstName());
n.setFirstName("八戒");
System.out.println(p.getName().getFirstName());
}
}
运行程序,输出:
悟空八戒
可以看到,main函数中定义Person类的对象p时,使用了Name型引用变量n来初始化它。而后面程序将n的FirstName作了修改,同时,这引起了了Person类实例p内的实例变量发生了改变,于是Person类便也不再是不变类了。
为了保护Person类的不可变性,这就要求我们不能够通过改变Person对象内的引用类型变量n的内容来改变Person对象。只要让程序无法访问到可变的name,这样也就无法使Person对象的内的成员变量发生改变,同时保持了Person类的不变性。将程序作如下修改:
public class Person {
private final Name name;
public Person(Name name) {
//设置name实例变量为临时创建的Name对象,该对象的FirstName和LastName与
//传入的name参数的FirstName和LastName相同
this.name=new Name(name.getFirstName(),name.getLastName());
}
public Name getName() {
//返回一个匿名对象,该对象的FirstName与LastName与
//该对象里的name的FirstName和LastName相同
return new Name(name.getFirstName(),name.getLastName());
}
public static void main(String[] args) {
Name n=new Name("悟空","孙");
Person p=new Person(n);
System.out.println(p.getName().getFirstName());
n.setFirstName("八戒");
System.out.println(p.getName().getFirstName());
}
}
运行程序,输出:悟空悟空
可以说明,改变Name型引用变量n内的值没有对Person类对象造成影响,从而保护了Person类的不可变性。以上就是Java中不可变类定义时要注意的一些小问题,在需要用到可变对象对不可变类的对象进行初始化时,可以选择创建参数与可变对象相同的临时对象对不可变量进行初始化,这样在可变对象内容发生改变时,不会影响到不可变类的对象实例变量的改变。
相关文章推荐
- Java学习笔记十四:如何定义Java中的类以及使用对象的属性
- Silverlight学习笔记[6] - 如何:定义 Windows Communication Foundation 服务协定
- Java学习笔记8 —— Java的类定义
- Java学习笔记之异常的定义和处理
- wpf学习笔记-如何获得MS定义好的模版
- [Silverlight学习笔记]如何获取ItemsControl的DataTemplate中定义的控件?
- 学习笔记 Flex和Java整合中如何进行配置
- 14. JAVA 枚举(Enum、类集EnumMap&EnumSet 、实现接口、定义抽象方法) ----- 学习笔记
- java编程思想学习笔记:如何选择继承与组合
- java学习笔记15——不可变类
- Java学习笔记14:接口只用于定义类型
- java(j2se)学习笔记----如何实现四舍五入?
- java学习笔记2--数组的定义
- 【Solr4.7.0学习笔记】系列之一:如何让solr和java程序整合
- SilverLight学习笔记--如何在xaml文件中操作用户在后台代码定义的类(2)--示例篇:创建一个登录控件(原创)(转载本文请注明出处)
- 【笔记】学习NServiceBus-如何定义你的输入队列的名称?
- Java学习笔记4:通过私有构造器强化不可实例化的能力
- 【Java 学习笔记】 TreeMap排序,Comparator的定义
- 【Solr4.7.0学习笔记】系列之一:java程序里面,如何用ajax访问solr程序?
- 内部类定义在局部学习笔记InnerClassDemo3.java