final可以用来修饰数据、方法和类。
一、 final数据
1. 用于基本类型
定义一个永不改变的编译时常量(编译时值已经确定);定义一个在运行时被初始化的值,一旦被初始化,就无法改变。
2. 用于对象引用
使引用恒定不变,即一旦引用被初始化指向某一对象,就无法再指向其他对象。但是被指向的对象本身是可以改变的。
import java.util.Random;
class Value{
int i;
public Value(int i) {this.i = i;}
}
public class TestFinal {
private static Random rand = new Random(47);
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
public static final int VALUE_THREE = 999;
private final int i4 = rand.nextInt(20);
static final int INT_5 = rand.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(22);
private static final Value VAL_3 = new Value(33);
private String id;
public TestFinal(String id) {
this.id = id;
}
public String toString() {
return id + ":" + "i4 = " + i4 + " INT_5 =" + INT_5;
}
public static void main(String[] args) {
TestFinal tf1 = new TestFinal("tf1");
// tf1.valueOne++;//The final field TestFinal.valueOne cannot be assigned
// tf1.VALUE_TWO++;//The final field TestFinal.VALUE_TWO cannot be assigned
// tf1.VALUE_THREE++;//The final field TestFinal.VALUE_THREE cannot be assigned
tf1.v1 = new Value(9);
// tf1.v2 = new Value(9); //The final field TestFinal.v2 cannot be assigned
tf1.v2.i++;
// tf1.VAL_3 = new Value(3);//The final field TestFinal.VAL_3 cannot be assigned
System.out.println(tf1);
TestFinal tf2 = new TestFinal("tf2");
System.out.println(tf2);
}
}
tf1:i4 = 15 INT_5 =18
tf2:i4 = 13 INT_5 =18
valueOne, VALUE_TWO,VALUE_THREE 都是final int,是编译期常量,不能被改变,static关键字只是强调只有一份,没有什么本质区别。VALUE_THREE是一种更加典型的常量定义方式,被定义为public,则可以被用于包之外,static表示只有一份,final表示其为常量。
i4,INT_5说明了final定义的数据也可以时运行时才确定其值。i4对于每个对象都是独特的,即每次创建一个新的对象,就会初始化产生一个i4。但是由于INT_5是static的,在类装载的时候被初始化,只有唯一的一份。所以对于tf1和tf2,i4的值是不同的,INT_5则相同。
对于对象引用,v2和VAL_3不能再指向其他对象,但是它们指向的对象的内容依然是可以改变的。
3.用于方法参数
在参数列表中被指定为final的参数,在在方法中无法被改变:
1.如果该参数是对象引用,则在方法中不能更改该参数引用所指向的对象;
2.如果是基本类型,数据的值不能被改变。
class Demo{
}
void with(final Demo d) {
// d = new Demo(); //The final local variable d cannot be assigned. It must be blank and not using a compound assignment
}
void f(final int i) {
// i++;//The final local variable i cannot be assigned. It must be blank and not using a compound assignment
}
二、final方法
final方法无法被继承类修改它的含义,无法被覆盖。而private关键字定义的方法,无法被继承类访问,则已隐式地被指定为了final,所以private方法不需要再添加final修饰词。
三、final类
被定义为final的类不允许被继承,其所有方法都隐式被指定为final方法。