final 数据
final关键字用于数据时,代表这个数据是一个常量,不可改变,这个数据通常属于基本数据类型。但有几点需要注意:
- 当final修饰引用数据时,代表的是引用不变,一旦引用指向一个对象,就无法把他改为指向另一个对象,然而对象自身是可以更改的。
- Java允许生成“空白final”,既可以先声明为final但不赋初值。如果空白final定义在对象中最为数据成员,必须在构造器中初始化。如果定义在其他地方,必须在使用前初始化。
测试如下:
public class FinalTest {
final int i = 0; // final修饰基本数据类
final Test t1 = new Test(); // final修饰引用数据类型
final int j; // 空白final,必须在构造器中初始化,否则会报错
public FinalTest(){
j = 1;
}
public static void main(String[] args) {
FinalTest ft = new FinalTest();
//ft.i = 2; // 无法更改值,报错
ft.t1.i = 3; //可以改变引用数据的值
System.out.println(ft.t1.i); // 输出3
//ft.t1 = new Test(); // 无法指向另一个对象,报错
final int a; // 空白final,在使用前初始化
}
}
class Test {
int i = 0;
}
另外,Java允许在参数列表中以声明的方式将参数指明为final,即不不能再方法内更改参数。
public class FinalParameter {
public void withFinal(final Test1 t){ // final修饰参数
//t = new Test(); // 不能更改引用所指向的对象,报错
}
public void withoutFinal(Test1 t){
t = new Test1();
}
public static void main(String[] args) {
FinalParameter fp = new FinalParameter();
fp.withFinal(null);
fp.withoutFinal(null);
Test1 t1 = new Test1();
}
}
class Test1{
public void print(){};
}
final方法
使用final修饰方法的原因有两个:
- final修饰的方法不能被覆盖。
- 能提高程序运行效率。在早期的Java中,如果一个方法被指明为final,编译器就会将针对该方法的所有调用都转换为内嵌调用。从Java SE5/6时,将效率问题交给了编译器和JVM去处理,而不需要使用final方法来优化了,只要在想要明确禁止覆盖时才将该方法设置为final。
实际上,类中所有的private都被隐式的指定为final。因为不能取用private方法,也就无法覆盖它。
final类
当用final修饰类时,无法继承该类,既该类不会有子类,final类中所有的类都被隐式的指定为final,因为无法覆盖它们,