Java中的关键字final
有三种可能会用到final:数据、方法、类
(一)final 数据
有时候将数据定义成用final进行定义是非常有用的:
a. 一个用不可改变的编译时常量(对于在编译期常量,编译器可以将常量用到任何会用到他的地方,减轻运行时的负担)
b. 一个在运行时被初始化的值,而你不希望改变他。
我们常常看到的是既是static又是final的定义,这是一段不能改变存储空间的域的定义。
对于基本类型我们用final,可是引用类型定义成final是什么意思呢?
同样很简单,一旦final的引用被初始化指向一个对象,就无法再改变它指向另一个对象。
下面说一个小例子作说明:
package com.edu.test;
import java.util.Random;
class Value{
int i;
public Value(int i){
this.i = i;
}
}
public class FinalTest{
private static Random rand = new Random(47);
private String id;
public FinalTest(String id){
this.id = id;
}
//下面定义的是编译时常量
private final int a1 = 1;
private static int a2 = 2;
//下面的使我们最常看到的定义方式
public static final int a3 = 3;
//下面虽然定义成final,但是却不是编译时常量
private final int b1 = rand.nextInt(10);
public static final int b2 = rand.nextInt(10);
private Value value1 = new Value(10);
//下面是将引用类型的final定义
private final Value value2 = new Value(20);
private static final Value value3 = new Value(30);
//用final修饰数组
private final int[] a = {1,2,3,4,5,6};
public String toString(){
return id + ":" + "b1=" + b1 + ",b2=" + b2;
}
public static void main(String args[]){
FinalTest ft1 = new FinalTest("obj1");
//下面是错误的(不可以改变其值)
//ft1.a1++;
//下面的是正常的
ft1.value1 = new Value(8);
//下面的当然就不行,不可以在用另外一个对象实例化
//ft1.value2 = new Value(8);
//ft1.value3 = new Value(8);
//value2虽然是final,不可以另外实例化,但是其本身的属性不是final的可以改变
ft1.value2.i++;
//下面对数组进行说明,其实和引用类型是一个性质的
ft1.a[1]++; //可以改变
//ft1.a = new int[5]; //a是final的数组,不可以被重新实例化
System.out.println(ft1);
System.out.println("*****创建另外一个对象*****");
FinalTest ft2 = new FinalTest("obj2");
System.out.println(ft1);
System.out.println(ft2);
}
}
我们来看一下运行结果还会有另外的收获:
obj1:b1=5,b2=8
*****创建另外一个对象*****
obj1:b1=5,b2=8
obj2:b1=3,b2=8
为什么重新创建一个对象ft2,b1的值变了,而b2的值却没有改变呢?
b1和b2只有在运行时在可以看到区别,在编译期间是看不出来的。
我们在创建对象的final的变量时候都是要实例化的,就是要给一个初始的值,有时候我们也会碰到所谓的空白final,意思很明了,就是没有初始值,但是我们必须在用之前给定一个值。
还有一种是final的形参,这种情况多用于匿名内部类传递数据。
(二)final 方法
就是不可以改变的方法,就是锁定,以防任何继承类修改他的含义。
其实所有的private方法都隐式的指定为final,因为在别的类中无法取用,自然就无法覆盖了。
(三)final类
知道了final方法,final类也比较好理解了,不允许别的类继承此类。