*** 可能使用到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类不能被继承。