java的final关键字可以修饰数据、方法和类。
- final修饰数据
final修饰的数据有一个特性,就是赋值之后不允许再次修改。什么样的数据赋值给final变量是有效的。总的来说是两种:
1、编译时的常数,也就是其值在编译时就是确定的,无需运行,例如:常数、常量字符串都是这种数据。
2、也可以是运行时确定的数据。
class FinalData{
private Random r = new Random();
final int a = r.nextInt(); //运行时确定
final int b = 30; //编译时确定,常量
final String s = "abc"; //编译时确定,常量字符串
}
因为final变量是只能被赋值一次,并且之后不能再修改,那么java肯定有一种机制就是final变量必须要赋值,而不是使用默认的值,要不然没有意义。那么java如何确保这种机制的正确执行呢?
final变量是在类里面进行赋值的,要么是在定义时就初始化,要么定义时不初始化,在每个构造函数里面初始化,还有就是定义时不初始化,在随后的代码块中初始化,例子:
class FinalData{
final int a;
FinalData(){
a = 10;
}
final int b = 20;
final int c;
{
c = 30;
}
}
-
final修饰方法
当final修饰方法时,就是要告诉使用者不能再子类中覆盖这个方法,否则编译器报错。当final和private修饰一个方法时,然后在子类中覆盖这个方法,就会出现很奇怪的事,编译没有错误。这时因为使用private修饰的方法是属于类内部的,本身就不能在子类中使用,更不用说覆盖,覆盖是覆盖父类的接口,private方法不是接口。因此在子类中覆盖并没有问题,在这里使用覆盖并不准确(因为前面说了覆盖是对于接口而言的),就是定义了一个子类的一个final private方法。另外,private方法本身就隐含final的意思。 -
final修饰类
这个类不能被继承,比如说String类。
那么当static final同时修饰一个变量,那么这个变量有什么特殊的呢?static修饰变量是在类的加载时就确定的,并且是在变量定义时就初始化,这就导致了变量不能在构造函数中执行初始化,只能定义时就初始化。