Java---final关键字

Concept

许多编译语言都有某种方法,来向编译器告知一块数据是恒定不变的。有时数据的恒定不变很用,比如 1. 一个永不改变的编译时常量 2. 一个在运行时被初始化的值,而你不希望它被改变。

对于编译器常量,编译器可以将该常量值代入任何可能用到它的计算式中,也就是说,可以在编译时执行计算式,这减轻了一些运行时的负担。在Java中,这类变量必须是基本数据类型,并且以关键字final表示。在对这个常量进行定义的时候,必须对其进行赋值。

final 数据
  1. 对于基本类型,final使数值恒定不变;对于对象引用,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法再把它改为指向另一个对象。然而,对象其本身却是可以被修改的,Java并未提供使任何对象恒定不变的途径(但可以自己编写类以取得使对象恒定不变的效果)。
  2. 一个既是static又是final的域只占据一段不能改变的存储空间。根据惯例,既是static又是final的域将用大写表示,并使用下划线分割各个单词。
Example
class Value{
    int i;
    public Value(int i ){ this.i = i;}
}

class Data{
    private static Random rand = new Random(47);
    private String id;
    public Data(String id) { this.id = id;}
    private final int v1 = 9;
    private final Value v2 = new Value(22);
    private Value v3 = new Value(11);
    private final int i4 = rand.nextInt(20);
    static final int INT_5 = rand.nextInt(20);
    private final int[] a = {1, 2, 3, 4, 5, 6};

    public static void main(String args[]){
        Data f1 = new Data("f1");//创建一个Data对象
        //!f1.v1++   这里错误是因为v1被声明为final 无法改变其值
        f1.v2.i++;//v2虽然被声明了为final v2的成员属性依然可以被改变
        //!f1.v2 = new Value(0);   v2被声明了final 所以v2这个引用不可以被改变
        f1.v3 = new Value(9);// v3没有被声明为final 可以改变
        for(int i = 0; i < f1.a.length;i++){
            f1.a[i]++;
        }//a被声明了final 但是数组里面的元素依然可以被改变
        //!f1.a = new int[3];   a作为引用却不可以被改变
        Data f2 = new Data("f2");//创建一个新的Data对象
        System.out.println(f1.i4);//15
        System.out.println(f2.i4);//13
        System.out.println(f1.INT_5);//18
        System.out.println(f1.INT_5);//18

    }
}

注意在f1和f2中,i4的值都是每个对象唯一的,但是INT_5的值不可以通过创建第二个Data对象而加以改变。这是因为它是static的,在装载时已被初始化,而不是每次创建新对象时都初始化。

我们也可以看出final声明一个引用以后,并不是认为无法改变它的值。而是意味着无法将这个引用指向另一个新的对象。这对数组具有同样的意义,因为数组只不过是另一种引用。

空白 final
  1. Java允许生成“空白final”,所谓空白final是指被声明为final但又未给定初值的域。无论什么情况,编译器都确保空白final在使用前必须被初始化。但是,空白final在关键字final的使用上提供了更大的灵活性,为此,一个类中的final域就可以做到根据对象而有所不同,却又保持其恒定不变的特性。
  2. 必须在域的定义处或者每个构造器中用表达式对final进行赋值,这是因为final域在使用前必须被初始化。
Example
class Poppet{
    private int i ;
    Poppet(int ii){ i = ii;}

}
class BlankFinal {
    private final int i = 0;
    private final int j;
    private final Poppet p;

    public BlankFinal(){
        j = 1;
        p = new Poppet(1);
    }
    public BlankFinal(int x) {
        j  = x;
        p = new Poppet(x);
    }
}
final 参数
  1. Java 允许在参数列表中以声明的方式将参数指定为final。这一特性主要用来向匿名内部类传递数据。
  2. 当参数为基本类型变量时,变量的值不可改变;当参数为引用类型时,参数的引用地址不可改变。
final 方法
  1. 使用final方法的原因是把方法锁定,以防任何继承类修改它的含义。这是出于设计的考虑:想要确保在继承中使方法行为保持不变,并且不会被覆盖。
  2. final修饰方法表示不允许被子类重写,但是可以被子类继承,不能修饰构造方法。
  3. 类中所有的private方法都隐式地指定为是final的。由于无法取用private方法,所以也就无法覆盖它。可以对private方法添加fianl修饰词,但这并不能给该方法增加任何额外的意义。
final 类
  1. 当将某个类的整体定义为final时(通过将关键字final置于它的定义之前),就表明了你不打算继承该类,而且也不允许别人这样做。换句话说,出于某种考虑,你对该类的设计永不需要做任何改动,或者出于安全的考虑,你不希望它有子类。
  2. 由于final类禁止继承,所以final类中所有的方法都隐式指定为是final的,因为无法覆盖它们。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值