final修饰符的使用:
1.final可以修饰变量,被final修饰的变量,被初始值的时候,不能再对其重新赋值;
1>:final 修饰实例变量:final 修饰实例变量必须在声明时显示赋值,可以在定义变量、非静态初始化块
、构造器中为final类型值赋值:
example: public class FinalTest{//定义时赋值 final String va1="asd"; final String va2; final String var3; //非静态初始化块 { va2="aasdasd"; } //在构造器赋值 public FinalTest(){ var3="ASdsa"; } }
需要注意的是:经过编译器的处理,这三种方式都会被抽取到构造器中赋初值
实质上:程序员只能在构造器里边对Final值赋值
2>:final 可以修饰类变量:final类变量可以在定义时、静态初始化块中进行赋值
example: class FinalClassStoreTest{ final static String Name="asdas"; static{ final static Stirng Sec__Name="asdasd"; } }
实质上,final类对象在编译器的作用下都是在static静态初始化块进行初始化赋值的,并且在之后
不可改变
3>:final==》宏变量==》宏代替
实例变量、类变量、局部变量在被final修饰之后本质上已经不再是一个变量了,而是变成了 一个常量
当定义final变量的时候时指定了初始值,而且该值就从此确定了下来,那么这个final值就是一个"宏变量"
编译器会把所有程序中所有用到该变量的地方直接替换成该变量的值
除了在给final类型值直接赋值外,如果被赋的表达式没有访问变量、调用方法,
而只是基本的算术运算表达式或字符串连接运算,
example:
String va_1=”asda“ final String va_2 =”asdas“+ va_1; //不是宏变量 final String va_3="asdas"+"asda"; //是宏变量 final String va_4="asdas"+String.valueof("asda"); //不是宏变量 boolean(va_4==va_3) //false
2.final方法不能重写:
1》.如果父类的方法被private修饰,不能被子类继承到,所有就实现了假重写;使用
@Override 会报错;
@Override可以检测该方法是否被重写,如果没有被重写就编译错误
example: class father{ final private void Display(){ //your code } } class son extends father{ //@Override 报错,因为此时并没有重写Display方法 void Display(){ //your code } }
2>当父类和子类并不在同一个包里边时,并且父类中的某个方法没有访问修饰符修饰(只用了final修饰),
此时就可以实现“假重写”;
使用@Override时会报错
3.如果程序需要在内部类中访问局部变量时,那么这个局部变量就必须使用Final符修饰:涉及到闭包(Closure)问题
Example: public class ClosureTest{ public static void main(){ final va=5; new Thread(new Ruunable(){ public void run(){ for(int i=0;i<10;i++) System.out.print("i"+va); //使用 try{ Thread.sleep(1000); }catch(e){ e.printStack(); } } }).start(); }}
当程序运行时,mian()线程很早就执行完毕,而当前并发的线程却并没有停止,本来va时属于main()作用域
的变量,现在被其他作用域所用,内部类扩大了变量的作用域,防止扩大局部变量的作用域,对变量的修改进而引起混乱
,所以当内部类引用局部变量时,局部变量必须修饰为Final