# final关键字

#### final(P140-142)

可能使用到final的情况有以下三种

* 数据
* 方法
* 类

#### final数据

有时数据的恒定不变是很有用的，比如

* 一个永不改变的编译时常量。
* 一个在运行时被初始化的值，而你不希望它被改变。

对于编译器常量这种情况，编译器可以将该常量值带入任何可能用到它的计算式中，也就是说，可以在编译器时执行计算式，这减轻了一些运行时的负担。在Java中，这类常量必须是基本数据类型，并且以关键字final表示。在对这个常量进行定义的时候，必须对其进行赋值。

一个既是static又是final的域只占据一段不能改变的存储空间。

对于基本类型，final使数值恒定不变。而用于对象引用，final使引用恒定不变。一旦引用被初始化指向一个对象，就无法再把它改为指向另一个对象。然而，对象其自身却是可以被修改的，Java并未提供使任何对象恒定不变的途径(但可以自己编写类以取得使对象恒定不变的效果)。这一限制同样适用于数组，它也是对象。

注意：我们不能因为某数据是final的就认为在编译时可以知道它的值。以下代码说明了这一点

```
private final int i = rand.nextInt(20);
```

**空白final**

Java允许生成空白final，所谓空白final是指被声明为final但又未给定初值的域。无论什么情况，编译器都确保空白final在使用前必须被初始化。但是，空白final在关键字final的使用上提供了更大的灵活性，为此，一个类中的final域就可以做到根据对象而有所不同，却又保持其恒定不变的特性。

```
class Poppet{
    private int i;
    Poppet(int i){
        this.i = i;
    }
}
```

final域通过在域的定义处或者每个构造器中用表达式对final进行赋值来保证其总是在使用前被初始化。

**final 参数**

Java允许在参数列表中以声明的方式将参数指明为final。这意味着你无法在方法中更改参数引用所指向的对象。

基本类型的参数被指明为final时，你只可以读参数，无法修改参数。这一特性主要用来向匿名内部类传递数据。

#### final方法(P143)

final修饰方法可以把方法锁定，以防任何继承类修改它的含义。

类中的private方法都隐式地指定为final的。

#### final类(P144-145)

当将某个类的整体定义为final时(通过将关键字final置于它的定义之前)，就表明了你不打算继承该类，而且也不允许别人这样做。

由于final类禁止继承，所以final类中所有的方法都隐式指定为final的，因为无法覆盖它们。

如果试图继承一个final类，会在编译器报错。
