final关键字在Java中是比较常用的关键字, 它的作用就像它的意思一样“最终的、不可改变的”。之所以用final关键字阻止改变,可能是设计或者效率的原因。因为这两个原因的很不相同,可能造成final关键字的误用。
final关键字的三种应用场合:数据,方法和类。
final修饰数据
final修饰数据的用法有两种。一是修饰基本数据类型(primitives)的数据成员,二是修饰对象引用类型(Object reference)的数据成员包括数组。这两点有些不同,当声明一个基本数据类型的数据成员为final时,需要给定一个初始值,final会将这个数据成员的值变成一个常数,后面的操作都不能改变这个数据成员的值。当final被用在对象引用而不是基本数据类型时,意思又不一样了。final会将引用变成一个常数,但是对象里面的数据是可以修改的。
代码演示:
class Value {
int i;
public Value(int i) {
this.i = i;
}
}
public class TestFinal {
private int value1 = 10;
private final int value2 = 10;
private Value v1 = new Value(10);
private final Value v2 = new Value(10);
private final int []a = {1,2,3};
public static void main(String[] args) {
TestFinal tf = new TestFinal();
tf.value1++; //可以改变
// tf.value2++; //错误,final不可改变
tf.v1 = new Value(10); //可以改变对象引用指向
// tf.v2 = new Value(11); //错误,final不能改变对象引用指向
tf.v2.i++; //正确
// tf.a = new int[3]; //错误,final不能改变数组的引用
tf.a[0]++; //正确
}
}
Java也允许创建空白的final数据成员,就是在声明数据成员为final时不给定初始值。但是编译器会确保空白的final数据成员在使用前必须要初始化。这样的用法具有更大的灵活性。
代码演示:
class Value {
private int i;
public Value(int i) {
this.i = i;
}
}
public class BlankFinal {
private final int i = 0;
private final int j;
private final Value v;
public BlankFinal() {
j = 1; //初始化空白final
v = new Value(1); //初始化空白final引用
}
public BlankFinal(int x) {
j = x; //初始化空白final
v = new Value(x); //初始化空白final引用
}
public static void main(String[] args) {
BlankFinal bf1 = new BlankFinal();
BlankFinal bf2 = new BlankFinal(47);
}
}
final修饰方法
fianl方法的作用主要是防止方法被继承的子类修改,就是阻止方法的覆盖或重写。但是子类还是可以使用父类中final修饰的方法。
任何类中的private方法都是隐性的final。因为你不能访问一个private方法,因此也不能覆盖它。所以你可以给private方法加final修饰符但是不会有额外的作用。
class A {
public A() {}
private final void f() {}
public final void g(){}
}
public class B {
public B() {}
public void f() {} //不能覆盖父类final方法
public void g(){} //不能覆盖父类final方法
public static void main(String[] args) {
B b = new B();
A a = b;
a.g(); //正确,不能覆盖但能访问父类final方法
}
}
final修饰类
final修饰类的作用是禁止被其他类继承。同时,类被定义成final后,类里面的所有方法都默认为final方法,也不能被覆盖或重写。常用的八大包装类和String类都是final类。
注:以上的内容有参考《Java编程思想》这本书里面的内容,如果有哪些地方不对的地方,欢迎大家指正。谢谢!