final关键字
关键字final有三个用途。其一,可以用于创建已命名常量的等价物。其二,在继承中使用final关键字阻止重写。其三,使用final关键字阻止继承。
一、创建已命名常量的等价物
可以将变量声明为final。这么做可以防止修改变量的内容,本质上就是将变量变成了常量。这意味着final必须在声明时进行初始化。可以通过两种方式完成这个工作:第一种方式,可以在声明时为其提供一个值;第二种方式,可以在构造函数中为其赋值。第一种方式最为常见。下面是一些例子:
final int FILE_NEW = 1;
final int FILE_OPEN = 2;
final int FILE_SAVE = 3;
final int FILE_SAVEAS = 4;
final int FILE_QUIT = 5;
现在,程序的后续部分可以使用FILE_OPEN等变量,就好像它们是常量,而不用担心它们的值会发生变化。final变量名全部使用大写,这是一种常见的编码约定。除了可以将变量声明为final之外,方法参数和局部变量也可以声明为final。将参数声明为final,可以防止在方法中修改参数。将局部变量声明为final,可以防止多次为其赋值。
二、使用final关键字阻止重写
虽然方法重写是Java中最强大的特性之一,但是有时会希望阻止这种情况的发生。为了禁止重写方法,可以在方法声明的开头使用final作为修饰符。使用final声明的方法不能被重写。下面的代码段演示了这种情况:
class A{
final void meth(){
System.out.println("This is a final method.");
}
}
class B extends A{
void meth(){//ERROR! Can't override.
System.out.println("Illegal!");
}
}
因为meth()被声明为fianl,所以类B中不能重写该方法。如果视图这么做的话,会导致编译时错误。
将方法声明为final,有时可以提高性能:编译器可以自由地内联对这类方法的调用,因为编译器知道这些方法不能被子类重写。当调用小的final方法时,Java编译器通常可以复制子例程的字节码,直接和调用方法的编译代码内联到一起,从而可以消除方法调用所需要的开销。内联是final方法才有的一个选项。通常,Java在运行时动态分析对方法的调用,这称为后期绑定。但是,因为final方法不能被重写,所以对final方法的调用可以在编译时解析,这称为早期绑定。
三、使用final关键字阻止继承
有时希望阻止类被继承。为此,可以在类声明的前面使用final关键字。将类声明为final,就隐式地将类的所有方法也声明为final。正如可能期望的,将类同事声明为abstract和final是非法的,因为抽象类本身是不完整的,它依赖子类来提供完整的实现。下面是final类的一个例子:
final class A{
//...
}
//The following class is illegal.
class B extends A{//ERROR! Can't subclass A
//...
}
正如注释所表明的,类B继承类A是非法的,因为类A已经被声明为final。