java不可变类示例

final关键字可以用于何处
修饰类:该类不可被继承
修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以
类变量:
实例变量:
形参: 注意可以修饰形参
局部变量
修饰方法:该方法不可被重写
final修饰成员变量
final修饰成员变量,必须显式的指定初始值,系统不会为final成员进行隐式初始化,不能在初始化前访问。
因为,不管是类变量还是实例变量,都有个初始化的过程,初始化赋值后便不能再赋值,如果不显式的指定初始值,那么这些变量就没有存在的意义
修饰类变量:
要么声明时指定
要么在静态块中指定
二者互斥,只能是其一
修饰实例变量:
要么声明时指定
要么非静态块中指定
要么构造方法中指定
三者任意两者互斥,只能是这三者之其一
final修饰局部变量
局部变量,不管有没有final修饰,都是必须显式初始化的
final修饰的形参,是不能赋值的
final修饰引用类型变量
final可以用来修饰一个引用类型变量,但只能保证这个变量始终指向同一地址
不能保证指向的对象本身发生改变
final与直接量
一个变量,不管是类变量、实例变量、局部变量,满足下面三个条件,便是一个直接量
用final修饰
在定义该final变量时指定了初始值。注意是定义时,不能在代码块中或者构造方法中
该初始值可以在编译时就被确定下来
对于直接量,在编译的时候,会用直接量把变量名替换掉,编译后的文件中是不存在这个变量的
Java用常量池来管理使用过的字符串直接量
final修饰方法
final修饰的方法不能被重写,比如作为根父类的Object就有一个.getClass()方法是用final修饰的
如果父类有一个private final修饰的方法,子类也有这个方法,private final修饰,方法签名也相同,注意这不是重写,这是两个无关的方法,
final修饰类
final修饰的类不能被继承,比如:
public final class Math extends Object {…}
不可变(immutable)类
不可变类:创建实例后,实例变量不可变,即实例的状态不能发生改变
8个包装类和String都是不可变类
如何定义一个不可变类:
用private和final修饰成员变量
提供带参数的构造器,用来初始化成员变量
只提供成员变量的get方法,不提供set方法
有必要的话重写equals()和hashCode()方法
如果成员变量是引用类型
这种情况要特别注意,上面的写法只能用于基本类型
对引用类型不可变的写法,基本原则就是隔绝外部对它的访问,主要要做好两点:
传递进来的引用类型对象不要直接用,而要根据其实例变量重新创建一个
外部访问时,根据这个对象的实例变量的值,重新创建一个对象返回
看下面的示例代码:
示例1:

public class Test{  
    public static void main(String[] args) { 
        Name n=new Name("师兄","大");
        System.out.println(n);            //Name@15db9742
        Person p=new Person(n,100);
        System.out.println(p);            //输出:[大师兄100岁]
        System.out.println(p.getName());  //Name@15db9742
        n.setFirstName("师兄");
        n.setLastName("二");
        System.out.println(p);            //输出:[二师兄100岁],不可变对象还是变了,再看下面一段代码
        System.out.println(p.getName());  //Name@15db9742
    }
}
class Person{
    private final Name name;
    private final int age;
    public Person(Name name,int age){
        this.name=name;
        this.age=age;
    }
    public Name getName(){
        return name;
    }
    public String toString(){
        return "["+name.getLastName()+name.getFirstName()+age+"岁]";
    }
}
class Name{
    private String firstName;
    private String lastName;
    public Name(){}
    public Name(String first,String last){
        firstName=first;
        lastName=last;
    }
    public String getFirstName(){
        return firstName;
    }
    public void setFirstName(String firstName){
        this.firstName=firstName;
    }
    public String getLastName(){
        return lastName;
    }
    public void setLastName(String lastName){
        this.lastName=lastName;
    }
}

示例2改写了两行:

public class Test{  
    public static void main(String[] args) { 
        Name n=new Name("师兄","大");
        System.out.println(n);            //Name@15db9742
        Person p=new Person(n,100);
        System.out.println(p);            //输出:[大师兄100岁]
        System.out.println(p.getName());  //Name@6d06d69c
        n.setFirstName("师兄");
        n.setLastName("二");
        System.out.println(p);            //输出:[大师兄100岁]。没发生改变
        System.out.println(p.getName());  //Name@7852e922
    }
}
class Person{
    private final Name name;
    private final int age;
    public Person(Name name,int age){
        this.name=new Name(name.getFirstName(),name.getLastName());  //此行改写
        this.age=age;
    }
    public Name getName(){
        return new Name(name.getFirstName(),name.getLastName());     //此行改写
    }
    public String toString(){
        return "["+name.getLastName()+name.getFirstName()+age+"岁]";
    }
}
class Name{
    private String firstName;
    private String lastName;
    public Name(){}
    public Name(String first,String last){
        firstName=first;
        lastName=last;
    }
    public String getFirstName(){
        return firstName;
    }
    public void setFirstName(String firstName){
        this.firstName=firstName;
    }
    public String getLastName(){
        return lastName;
    }
    public void setLastName(String lastName){
        this.lastName=lastName;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值