文章内容源于对《疯狂java讲义》及《疯狂Java:突破程序员基本功的16课》学习和总结。
一、 final成员变量
final 修饰变量时,表示该变量一旦获取了值就不可以改变了。
但是我们知道,当一个类被加载,或者是实例化对象时,系统会为类成员赋初始值,所以,final关键字修饰的成员变量,必须有程序员指定初始值,一旦指定了初始值,就不可以再改变。
其初始化可以在两个地方:
类Field:必须在声明该变量时或静态初始化快中指定初始值。
实例Field: 必须在非静态初始化块、声明该Field或构造器中指定初始值。
示例:
public class FinalVariableTest { //定义成员变量时指定默认值,合法。 final int a = 6; //下面变量将在构造器或初始化块中分配初始值 final String str; final int c; final static double d; //既没有指定默认值,又没有在初始化块、构造器中指定初始值, //下面定义char Field是不合法的。 //final char ch; //初始化块,可对没有指定默认值的实例Field指定初始值 { //在初始化块中为实例Field指定初始值,合法 str = "Hello"; //定义a Field时已经指定了默认值, //不能为a重新赋值下面赋值语句非法 //a = 9; } //静态初始化块,可对没有指定默认值的类Field指定初始值 static { //在静态初始化块中为类Field指定初始值,合法 d = 5.6; } //构造器,可对既没有指定默认值、有没有在初始化块中 //指定初始值的实例Field指定初始值 public FinalVariableTest() { //如果初始化块中对str指定了初始化值, //构造器中不能对final变量重新赋值,下面赋值语句非法 //str = "java"; c = 5; } public void changeFinal() { //普通方法不能为final修饰的成员变量赋值 //d = 1.2; //不能在普通方法中为final成员变量指定初始值 //ch = 'a'; } public static void main(String[] args) { FinalVariableTest ft = new FinalVariableTest(); System.out.println(ft.a); System.out.println(ft.c); System.out.println(ft.d); } }
编译运行结果:
6
5
5.6
二、 final局部变量
对于使用final修饰局部变量,即可以在定义时指定默认值,也可以不指定默认值;
如果一旦赋了初始值,则之后都不可以再修改变量值。
public class FinalLocalTest { public static void main(String[] args) { //定义一个普通局部变量 final int a = 5; System.out.println(a); } }
三、 内部类中的局部变量
另外方法中的内部类在用到方法中的参变量时,此参变也必须声明为final才可使用:
public class INClass { void innerClass(final String str) { class IClass { IClass() { System.out.println(str); } } IClass ic = new IClass(); } public static void main(String[] args) { INClass inc = new INClass(); inc.innerClass("Hello"); } }
四、 final宏替换
final有一个很重要的概念,就是宏替换;宏替换的应当满足的条件:
· 使用final修饰符修饰变量
· 在定义该final变量时只定了初始值
· 该初始值可以在编译时就被确定下来。
public class FinalLocalTest { public static void main(String[] args) { // 定义一个普通局部变量 final int a = 5; System.out.println(a); } }
总结:
1. final修饰基本类型和引用类型有所不同,final修饰基本类型变量时,只要基本类型被赋初始值,则不可改变; 但final修饰引用类型时,引用的地址不可改变,但是引用的值是可以改变的。
2. final执行宏替换时,在程序运行过程中,有替换的值直接参与程序的执行,而并非变量。
3. final修饰的方法不可重写,修饰的类不可继承。