java final 关键字

一、作用

由于语境(应用环境)不同,final 关键字的含义可能会稍微产生一些差异。但它最一般的意思就是声明“这个东西不能改变”。
final 关键字的三种应用场合:数据、方法以及类 

二、 final修饰数据

    许多程序设计语言都有自己的办法告诉编译器某个数据是“常数”。常数主要应用于下述两个方面:
    (1) 编译期常数,它永远不会改变
    (2) 在运行期初始化的一个值,我们不希望它发生变化
      对于编译期的常数,编译器(程序)可将常数值“封装”到需要的计算过程里。也就是说,计算可在编译期间提前执行,从而节省运行时的一些开销。在 Java 中,这些形式的常数必须属于基本数据类型(Primitives),而且要用 final关键字进行表达。在对这样的一个常数进行定义的时候,必须给出一个值。
      无论static还是 final字段,都只能存储一个数据,而且不得改变。

    final修饰对象 

    对于基本数据类 型,final 会将值变成一个常数;但对于对象句柄,final 会将句柄变成一个常数。
   进行声明时,必须将句柄 初始化到一个具体的对象。而且永远不能将句柄变成指向另一个对象。然而,对象本身是可以修改的。这一限制也适用于数组,它也属于对象。
    如:

 public class FinalData {
    static class Value {
        int i = 1;
    }

    final int i1 = 9;
    static final int I2 = 99;
    //由于i1和 I2都是具有 final属性的基本数据类型,并含有编译期的值,
    //所以它们除了能作为编译期的常数使用外,在任何导入方式中也不会出现任何不同。
    
    
    public static final int I3 = 39;
    //I3是我们体验此类常数定义时更典型的一种方式:public表示它们可在包外使用;
    //Static 强调它们只有一个;而 final 表明它是一个常数。注意对于含有固定初始化
值(即编译期常数)的 fianl static基本数据类型,它们的名字根据规则要全部采用大写。


    final int i4 = (int) (Math.random() * 20);
    static final int i5 = (int) (Math.random() * 20);
    //i5 在编译期间是未知的,所以它没有大写。
    //不能由于某样东西的属性是final,就认定它的值能在编译时期知道。
    //i4 和i5 向大家证明了这一点。它们在运行期间使用随机生成的数字。
    //将final 值设为static 和非static 之间的差异。
    //只有当值在运行期间初始化的前提下,这种差异才会揭示出来。
    //因为编译期间的值被编译器认为是相同的。这种差异可从输出结果中看出:
    //fd1: i4 = 15, i5 = 9
    //Creating new FinalData
    //fd1: i4 = 15, i5 = 9
    //fd2: i4 = 10, i5 = 9
    //注意对于fd1和 fd2来说,i4的值是唯一的,
    //但 i5的值不会由于创建了另一个FinalData 对象而发生改变。那是因为它的属性是static,
    
    
    Value v1 = new Value();
    final Value v2 = new Value();
    static final Value v3 = new Value();
    
    
    //final Value v4; 
    // 必须将V4句柄    初始化到一个具体的对象。
    
    
    final int[] a = {1, 2, 3, 4, 5, 6};

    public void print(String id) {
        System.out.println(
                id + ": " + "i4 = " + i4 +
                        ", i5 = " + i5);
    }

    public static void main(String[] args) {
        FinalData fd1 = new FinalData();
        
        //fd1.i1++;
        // Error: can't change value,不能改变final修饰的基本类型的值
        
        
        //fd1.v2 = new Value(); 
        // Error: Can't,对于已经用finale修饰的对象且已经句柄初始化到一具体对象,永远不能将句柄变成指向另一个对象
        
        
        fd1.v2.i++;
        // 无法重新初始化V2,但是对象本身是可以修改的
        
        
        // fd1.v3 = new Value(); 
        //对于已经用finale修饰的对象且已经句柄初始化到一具体对象,永远不能将句柄变成指向另一个对象
        
        
        fd1.v1 = new Value(); 
        // OK -- not final
        
        
        //fd1.a = new int[3];
        //不能将数组句柄重新指向另一个对象
        
        for (int i = 0; i < fd1.a.length; i++){
            fd1.a[i]++; // Object isn't constant!
        }
        fd1.print("fd1");
        System.out.println("Creating new FinalData");
        FinalData fd2 = new FinalData();
        fd1.print("fd1");
        fd2.print("fd2");
    }
}

总体来说将数组或者对象的句柄变成final 看起来似乎不如将基本数据类型变成 final那么有用。

三、 final修饰方法

     之所以要使用final 方法,可能是出于对两方面理由的考虑。第一个是为方法“上锁”,防止任何继承类改变它的本来含义。设计程序时,若希望一个方法的行为在继承期间保持不变,而且不可被覆盖或改写,就可 以采取这种做法。
      采用final 方法的第二个理由是程序执行的效率。前提是方法体积很小。通常,只有在方法的代码量非常少,或者想明确禁止方法被覆盖的时候,才应考虑将一个方法设为final。

四、final修饰类

    如果说整个类都是final(在它的定义前冠以 final关键字),就表明自己不希望从这个类继承,或者不允许其他任何人采取这种操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值