final关键字用来表明“不可改变”,final可作用在以下3种类型:数据,方法,类
1. final数据
Java中用final来定义常数
1.1 编译期常数,必须为基本类型,用final修饰
final int f1 = 22;
static final float f2 = 2.322;
public static final int FINT = 214; //约定俗成,static final修饰的基本数据类型的名字都大写
//f1 = f1 + 2; //error as f1 is final
1.2 运行期初始化一个值,不希望它变化
final int i4 = (int)(Math.random()*20);
static final int i5 = (int)(Math.random()*20);
//i4 = 8; //error as i4 is final
1.3 如果final声明的句柄是指向一个对象,则表示该句柄始终指向这个对象,不能将它指向其他对象,但是对象本身是可以变的。
class TestClass {
final int f1 = 20;
int f2 = 20;
}
class Test {
public static void main(String[] args) {
TestClass t1 = new TestClass();
final TestClass t2 = new TestClass();
TestClass t3 = new TestClass();
//t1.f1 = 30; //error as f1 is final
t1.f2 = 80;
//t2.f1 = 20; //error as f1 is final
t2.f2 = 30;
t1 = t3;
//t2 = t3; //error as t2 is final
}
}
1.4 空白final
定义一个final字段,但是不初始化,留给类构造方法来初始化(如果有多个构造方法,每个方法都要对空白final字段初始化),这样来保证每个对象都有一个不能改变但是值却不同的final字段。
class TestClass {
final int f1 = 20;
int f2 = 20;
final int f3; //blank final
public TestClass() {
f3 = 2; //should initialize f3 in every constructor
}
public TestClass(int i) {
f3 = i; <span style="font-family: Arial, Helvetica, sans-serif;">//should initialize f3 in every constructor</span>
}
}
1.5 final参数
方法参数也可以设置为final,表明此参数句柄不能指向别的对象,如果是基本数据类型,则不能改变其值。
class Test {
int i = 0;
}
class TestClass {
public void f(int i) { i = i * 2; }
//public void f2(final int i) { i = i * 2; } //error as i is final
public void f3(Test t) { t = new Test(); }
//public void f4(final Test t) { t = new Test(); } //error as t is final
}
2. final方法
final方法有两个作用:防止被子类覆盖/改写,加快方法执行速度
2.1 声明为final的方法,在继承时子类不能进行覆盖(重载)
2.2 编译器可以将final方法’嵌入‘到调用它的外部方法中,免去’调用‘的开销(压栈,开始执行调用方法,跳回,清除堆栈,返回值)。但是当final方法主体过大,嵌入代码的开销大于调用的开销,编译器可自行决定是否进行嵌入。
2.3 类中所有的private 方法都是final方法,private方法前加不加final没有影响
3. final类
定义为final的类禁止继承,如果想要明确该类不应该被继承,就把它设置为final类。final 类的数据成员可以为final也可以不是final,根据需要决定。然而final类中所有的方法默认都是final的,我们可以为final类中的方法加final标志,但是没有任何意义。