Java中的final关键字解析

本文详细解析了Java中final关键字的多种用法,包括final与基本数据类型、类、方法及对象引用的关系,并探讨了final与private、abstract的区别,以及在匿名内部类中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

final关键字应该是java中出现频率还算比较高的,用法其实也比较简单,就是它修饰的后面的那个东西,无论是变量、方法或者类,在初始化后都不能被改变了。本文结合代码,进一步对final+xxx进行解析。

一、final+基本数据类型

如果在此时还对该数据类型的变量进行了初始化,那么就“相当于”一个常量了。
示例代码如下:

public class FinalTest {
    final int i = 9;
}
public class Try {

    public static void main(String[] args) {
        FinalTest finalTest = new FinalTest();
        finalTest.i = 10;
    }
}

我是在IDEA 20.3中运行Try.java的,在Build阶段就报错:

java: 无法为最终变量i分配值

虽然看起来final也能和static final一样,构造出常量,但二者还是有区别的,后者是真正的常量表示方式。其中的区别我觉得有两个:
(1) 我们后面会讲到final可以+空白,也就是可以定义"final int i;",只要在该类的构造方法中对i进行初始化了,就不会报错;而static final修饰的变量(其实是常量了)必须初始化。
(2) static意味着这个变量是类所有的,而非对象所有的,正如(1)中所说,如果不同变量给final修饰的变量i赋的值不同,那么i并不能称为是常量;而static final修饰的常量对所有该类的对象都是相同的。

二、final+类

此时该类将不能被继承。
示例代码如下:

public final class FinalTest {
    final int i = 9;
}

class FinalTestExtend extends FinalTest {
    
}

bulid时会报错:

java: 无法从最终FinalTest进行继承

Java中有一些不能被继承的类,如Integer等包装类,String等,就是用到了final关键字

三、final+方法

此时该方法不能被重写和覆盖。
示例代码如下:

public class FinalTest {
    int i = 9;
    public final void methodTest() {
        System.out.println("测试final+方法");
    }
}

class FinalTestExtend extends FinalTest {
    public void methodTest() {
        System.out.println("在子类中继承重写final+方法");
    }
}

bulid时会报错:

java: FinalTestExtend中的methodTest()无法覆盖FinalTest中的methodTest()
被覆盖的方法为final

四、final+对象引用

此时该对象引用只能引用到已经确定的对象,不能再更换。不过这个对象内部可以发生变化。
示例代码:

public class FinalTest {
    int i = 9;
    public void methodTest() {
        System.out.println("测试final+");
    }
}
public class Try {

    public static void main(String[] args) {
        final FinalTest reference = new FinalTest();
        reference.methodTest();

        reference.i = 10; // 可以正常改变对象的成员变量

        reference = new FinalTest(); // 指向一个新对象时会报错
    }
}

build时报错:

java: 无法为最终变量reference分配值

五、final+空白

这里就是我们在“一、final+基本数据类型”中所提到的,可以final修饰后的对象或基本数据类型不赋值,留到构造方法中去赋值。
示例代码如下:

public class FinalTest {
    int i = 9;
    public void methodTest() {
        System.out.println("测试final+");
    }
}

public class Try {

    private final int try_i;
    private final FinalTest finalTest;

    public Try(int x, FinalTest y) {
        try_i = x;
        finalTest = y;
    }

    public static void main(String[] args) {
        FinalTest ft = new FinalTest();
        Try t = new Try(9, ft);
        t.finalTest.methodTest();
    }
}

可以正常运行程序,输出:

测试final+

final与private

所有的private方法都隐式指定为final都无法覆盖。

final与abstract

final与abstract可谓是水火不容,这也是一道最基础的java判断题:final绝对不能和abstract一起用。
因为abstract修饰的类,希望子类可以重写父类中所有的方法,但final又不允许该类被继承;abstract修饰的方法,希望子类能够重写这个方法,但final又不允许该方法被重写。因此,这两个关键字是不允许同时用来修饰一个类或方法的。

匿名内部类中的final

在匿名内部类中,为了保持参数的一致性,若所在的方法的形参需要被内部类里面使用时,该形参必须为final。这也是最近才看到的一点,先记录下来,有空了来补充一下实例。

参考博客:https://blog.youkuaiyun.com/u013309870/article/details/52137222

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值