*** 可能使用到final的三种情况:数据、方法和类 ***
*** 使用final的理由:设计的需要和运行效率 ***
一、final变量
- 一个永不改变的编译时常量,也就是一经初始化将不能被改变;
- 可在编译时带入任何用到它的计算式进行执行,这种final常量必须是基本数据类型,并以关键字final表示,这将减轻一定的运行时负担;
- 对于对象引用,final将使引用恒定不变,即一旦引用初始化指向一个对象将不能改为指向另一个对象;
public class TestFinal{
private final String st="Hello Final";
public static void main(Stirng[] args){
st=new String();//报错,st不能指向其他对象
st=new String("Error")//报错
}
}
- 既有static又有final的域(即编译期常量,其只占用一段不能改变的存储空间)将用大写表示,并用下划线分隔各个单词;
public static final int NUM_MERBER=10;
- 在对常量进行定义的时候,必须对其进行赋值。(也就是在变量被送到编译器中使用前必须赋值,可以在定义处和构造器处)
二、空白final
指声明为final但又未给定初值的域,但是编译器又要求在使用前必须要初始化,所以一般会在构造器中进行初始化,这样会使final更灵活,实例如下:
public class BlankFinal{
private final int i;
private final People p;
public BlankFinal(){ //通过构造器进行赋值
i=1;
p=new People(1);
}
public BlankFinal(int x){
i=x;
p=new People(x);
}
public static void main(String[] args){
new BlankFinal();
new BlankFinal(11);
}
}
class People{
private int i;
People(int i){this.i=i;}
}
三、final参数
final修饰的基本类型和引用类型可作为参数进行传递,但是这些参数只能读却不能进行修改,实例如下:
public class TestFinal{
TestFinal(){}
void f(final TestFinal tf){
tf=new TestFinal();//报错,因为此时的引用tf已经指向了传入的对象,不能再指向其他对象
}
void f(final int i){
i++;//报错,此时i为final常量不能改变
}
int f(final int i){
return i+1;//正确
}
}
final的这一特性主要用来向匿名内部类进行数据传递。
四、final方法
使用final方法的俩个原因:
*第一,把方法锁定,以访任何继承类修改它的含义,即确保在继承中使方法保持不变,并且不会被覆盖。
第二,起初是通过此方式提高运行效率,因为编译器会将final方法进行内嵌调用。但是随着Java版本的更新,效率问题主要依赖编译器和JVM,所以现在更倾向于原因一。
要注意的一个点是:private方法其实默认的是final方法,所以private方法是不能被子类方法覆盖的。
五、final类
在Java类添加final关键字的主要作用是使此类不能被任何类继承(即此类不可能有任何子类),这种做法一般出于对安全因素的考虑。一旦这个类被定义为final,那么这个类中的所有域和方法都将隐式的被指定为final。
***********************************************************************************
总而言之,用简短的一句话描述就是:final变量不能被二次赋值,final方法不能被覆盖,final类不能被继承。