final关键字


Java 的 final 关键字,通常指的是“这是无法改变的”。本文介绍 final 关键字的三种用法,即变量、方法和类。

final 变量

final 来修饰一个成员变量,就是告诉编译器这个变量是恒定不变的,我们通常希望达到以下效果:

1. 一个永不改变的编译时常量
2. 一个在运行时被初始化的值,并且不希望它被改变

对于编译时常量这种情况,编译器可以将常量值带入任何可能用到的计算式中,可以在编译时执行计算式,减轻运行时的负担。这类常量必须是基本数据类型,并且在定义的时候,要显示地初始化,初始化可以直接赋值,也可以在代码块或者构造器中来指定初始值。

当 final 修饰的成员变量是对象引用时,引用是不变的,一旦这个引用被初始化指向一个对象,就无法再将其指向另一个对象,但是对象其自身是可以被修改的。

public class FinalTest {

    //基本类型
    private final int num_1 = new Random(12).nextInt();
    public static final int NUM_2;

    //字符串
    private final String str_1;
    private static final String STR_2 = "str_2";

    //对象
    private final Value value_1;
    private static final Value VALUE_2 = new Value(22);

    //数组
    private final int[] a = {1, 2, 3};

    /**
     * 有参构造器
     * @param str
     */
    public FinalTest(String str) {
        this.str_1 = str;
    }

    //代码块
    {
        value_1 = new Value(12);
    }

    //静态代码块
    static {
        NUM_2 = 2;
    }
    
    public static void main(String[] args) {
        //final 修饰的对象,可以改变自身
        VALUE_2.i = 3;
        VALUE_2.i = 4;
    }
}

class Value {

    int i;

    public Value(int i) {
        this.i = i;
    }
}

我们可以看到 final 修饰的变量,可以在定义的时候初始化,也可以在构造器或者代码块中初始化。一个即是 static 又是 final 的域只占据一段不能改变的存储空间。NUM_2 就是一个典型的常量的定义,定义为 static,表示只有一份,定义为 final,则表示它是一个常量。

带有恒定初始值(即:编译期常量)的 final static 的成员全部用大写字母,并且单词之间用下划线隔开。

不能因为某个数据是 final 的就认为在编译期可以知道它的值,比如上面代码中的 num_1,它是在运行时使用随机数来初始化的。

不能因为某个对象是 final 的,就认为无法改变它的值,比如上面代码中的 VALUE_2,final 表示它无法指向另一个对象,但是可以改变自身,这对数组具有同样的意义,数组也不过另一种引用。

final 还可以用来修饰参数,如下:

/**
 * final 修饰参数
 * @param num
 */
public static void test(final int num) {
    System.out.println(num + 1);
    //无法改变
    //System.out.println(++num);
}

当用 final 修饰参数的时候,就意味着这个参数只能读取,不能改变。这个特性主要用于向匿名内部类传递参数。

final 方法

当我们使用 final 来修饰方法的时候,就是想确保这个方法的行为保持不变,并且不会因为继承而被覆盖。类中所有的 private 方法都隐式地指定为 final 的,由于外部的类无法取用 private 方法,所以也就无法覆盖它。可以使用 final 关键字来修饰 private 方法,只是显得有点多余就是了。

“覆盖”只有在某方法是父类的接口的一部分时才会出现,比如使用 public, default, protected 来修饰的方法,如果某方法为 private,它就不是父类的接口的一部分,所以除了把它看成是作为归属类的组织结构的原因而存在外,其他的任何原因都不需要考虑它。

final 类

当使用 final 来修饰类的时候,就表明你对这个类的内容很自信,不需要做任何变动,或者出于安全的考虑,不打算继承该类,而且也不允许别人这样做。最常见的就是 java.lang.String 这个类了,它的定义如下:

package java.lang;
//省略导包语句和注释

public final class String
implements java.io.Serializable, Comparable, CharSequence {

由于 final 类禁止继承,所以 final 类中的所有的方法都隐式地指定为 final 的,无法被覆盖,可以给 final 类的方法添加 final 关键字,当然,这也是多余的。

也正是由于 final 类被禁止继承,所以如果将一个方法指定为 final 的,这可能就会妨碍你的队友通过继承来复用你的类,而这只是因为你没有想到它会以那种方式被运用。所以,使用 final,还需慎重。

欢迎关注公众号:一盐难进

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值