final关键字在java中是一个很重要的关键字,其实按照其字面意思理解,就可以一窥这个关键字端倪,final的本意是最终的。所谓最终的,其最重要的特征就是不能修改,由此衍生出的许多细节均应以这个特征作为基础。
final可以修饰类、方法、变量。变量包括成员变量和局部变量。
1.修饰类
final修饰过的类不能被继承,如下的代码在ide中是会报错的。
final class Father{ } //The type son cannot subclass the final class Father class son extends Father{ }
2.修饰方法
final关键字修饰过的方法不能被子类重写。
class Father { public final void father_func() { System.out.println("father function"); } } class son extends Father { //Cannot override the final method from Father public void father_func() { } }
其实不管是final修饰的类不能被继承,还是final修饰的方法不能被子类重写,都是要保证这个类,这个方法时最终的,不能再被更改。这也符合final的本意。
3.修饰成员变量
final修饰的成员变量只能被赋值一次,而且必须在声明的同时或者构造函数中显式赋值,然后才能使用。否则ide会给出提醒。因为不像普通的成员变量,即便不显式初始化,系统也会默认初始化。
以下代码会出错。
public class FinalDemo { final Father f; //The blank final field f may not have been initialized public FinalDemo(){ } public static void main(String args[]) { } } class Father { public final void father_func() { System.out.println("father function"); } }
这样写才正确
public class FinalDemo { final Father f; public FinalDemo(){ f=new Father(); } public static void main(String args[]) { } }
4.修饰局部变量
final修饰的局部变量只能被赋值一次。有时候我们方法的形式参数(这也相当于一个局部变量)用final 来声明,目的就是告诉编程的人,不要再在方法体里面给这个变量去赋值了。
如下代码是错误的。
class Father { public void func(final int y){ //The final local variable y cannot be assigned. It must be blank and not using a compound assignment y=3; System.out.println(y); } }
既然y被final修饰,它就不能在方法体中继续赋值。修改成如下,并调用才是正确的。
public class FinalDemo { public static void main(String args[]) { Father f=new Father(); f.func(1); f.func(3); } } class Father { public void func(final int y){ System.out.println(y); } }
上述执行的结果是1和3。两次调用func,分别传入1和3给final形参y。此处不要认为我修改了y的值,我调用了两次func方法,两次的局部变量并不是同一个。所以不存在重复赋值的说法。
如果在方法体中定义一个final类型的局部变量,则只能给他赋值一次,不能重复赋值,这很好理解。当然也不能不赋值,这是最基本的,方法体中不管是不是final修饰的局部变量,都应该先被赋值才能使用。
5.如果一个类中的成员变量,除了用final修饰,还加上了static,那么他就有两层的属性,首先是静态的,可以直接通过类名直接访问得到。其次它是不可再被修改的。那么这种类型的变量我们可以称之为静态常量,它必须在声明的时候就直接显式初始化,即便在构造函数中都不能再初始化(可以理解为静态变量并不需要实例化就可以访问到,所以有可能不会执行到构造函数里面的代码,这就无法保证这个final变量一定会被初始化,于是干脆在声明的时候就初始化,最为保险)。
这种静态常量可以直接通过类名来访问,当我们再加上一个访问权限修饰符,比如public以后,这就成为了一个全局的常量,在整个项目中都能被访问到。在项目中,我们经常在一个类中写满了public static final类型的变量,并且命名为constant.java。然后通过constant.x来获取这些常量。