Java中的final关键字解析
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