final 关键字可以修饰不同的内容, 这些内容仅包括一个变量, 一个方法或者一个类, 以下是 final 修饰这些内容的作用:
final 变量: 表示该变量为常量, 即只能初始化一次
final 方法: 表示该方法不能被重写
final 类: 表示该类不可以被继承
final 变量
当一个变量被 final 关键字修饰时, 意味着它的值不可以被修改了, 也就是说, 这个变量表示一个常量. 这也意味着 final 变量必须被初始化. 如果一个 final 变量表示的是一个对象的引用, 那么该变量就不能重新表示另一个对象的引用了, 但是这个 final 变量指向的对象的内部状态是可以改变的, 例如, 我们可以向一个 final array 或者 final collection 中增加或者删除元素. 另外, 使用大写字母和下划线表示一个 final 变量是个好习惯.
- Examples
- // a final variable
- final int THRESHOLD = 5;
- // a blank final variable
- final int THRESHOLD;
- // a final static variable PI
- static final double PI = 3.141592653589793;
- // a blank final static variable
- static final double PI;
初始化一个 final 变量
我们必须初始化一个 final 变量, 否则编译器将会抛出错误. 一个 final 变量只能被初始化一次, 可以通过初始化器或者初始化语句对其进行初始化. 有三种方法可以初始化一个 final 变量:
在声明 final 变量时就对齐初始化, 这是最常用的初始化方式. 当一个 final 变量在声明的时候没有被初始化, 这个变量就被成为 blank final 变量, 那么下面的两种方法就是初始化一个 blank final 变量
blank final 变量可以由 instance-initializer 代码块或者构造函数进行初始化. 如果有多个构造函数, 那么这个 blank final 变量必须在每一个构造函数中都要进行初始化, 否则编译时报错.
一个 blank final static 变量可以在内部 static 代码块中初始化
- Examples
- // 初始化 final 变量的方法
- class Test {
- // 直接初始化
- final int THRESHOLD = 5;
- //blank final 变量
- final int CAPACITY;
- final int MAXMUM;
- //blanck static final 变量
- static final int MINIMUM;
- // 使用初始化器
- {
- CAPATICY = 25;
- }
- // 使用 static 代码块
- static {
- MAXMUM = 125;
- }
- // 使用构造函数
- public Test() {
- MINIMUM = -1;
- }
- }
什么时候需要使用 final 变量
一个普通变量和一个 final 变量之间唯一的区别就是一旦给 final 变量赋值, 则该变量的值将不可以再被改变. 因此, final 变量只能用于我们希望在整个程序执行过程中保持不变的值.
final 变量的值是对象的引用
当一个 final 变量是一个对象的引用, 我们把这个变量称为引用 final 变量 (reference final variable), 例如一个 StringBuffer 的 final 变量可以是 final StringBuffer sb, 我们知道一个 final 变量是不可以再重新赋值的, 但是这个 final 变量指向的对象的内部状态是可以改变的, 这种 final 属性可以称为非传递性.
- Examples
- class Test
- {
- public static void main(String[] args)
- {
- // a final reference variable sb
- final StringBuilder sb = new StringBuilder("Test");
- System.out.println(sb);
- // changing internal state of object
- // reference by final reference variable sb
- sb.append("ForTest");
- System.out.println(sb);
- }
- }
- // 输出为:
- //Test
- //TestForTest
- Note
a. final 变量不能重新赋值, 否则出现编译错误
b. 局部 final 变量必须在其创建后就对其进行赋值
c. 对比 C++ 的 const 变量, const 变量在声明的时候就需要赋初值, 而 final 变量可以先声明再赋值, 但只能赋值一次
d. foreach 循环中, final 修饰变量是合法的, 栗子如下
- // Java program to demonstrate final
- // with for-each statement
- class Test
- {
- public static void main(String[] args)
- {
- int arr[] = {
- 1, 2, 3
- };
- // final with for-each statement
- // legal statement
- for (final int i : arr)
- System.out.print(i + " ");
- }
- }
- // 输出: 1 2 3
这里可以这样使用的原因是每次迭代时相当于重新对 i 进行了声明
final 类
final 类无法被继承, 有两种使用情况:
定义一个 final 类来阻止其他类继承, 因为 final 类是无法被扩展的, 比如所有的封装类 Integer,Float 等都是 final 类
另一种 final 类是创建一个不可变类, 像预定义的 String 类, 如果不使用 final 关键字我们是无法创建一个不可变类的
final 方法
一个被 final 修饰的方法是无法被重载的, 对于一个含有 final 方法的父类, 在其派生类中该方法必须和父类中的方法保持相同的实现
- Example
- class A
- {
- final void m1()
- {
- System.out.println("This is a final method.");
- }
- }
- class B extends A
- {
- void m1()
- {
- // COMPILE-ERROR! Can't override.
- System.out.println("Illegal");
- }
- }
来源: http://blog.51cto.com/acevi/2439073