简述final
final修饰的类表示不可被继承,修饰方法表示此方法不可以被子类覆盖,但是可以被重载,修饰变量表示变量一旦被赋值就不可以更改它的值(基础类型是值,引用类型是地址)
修饰成员变量
a. 如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初始值。
b. 如果final修饰的是成员变量,可以在非静态初始化块、声明该变量或者构造器中执行初始值。
修饰局部变量
系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。因此使用final修饰局部变量时,即可以在定义时指定默认值(后面的代码不能对变量再赋值),也可以不指定默认值,而在后面的代码中对final变量赋初值(仅一次)
public class FinalReferenceTest{public static void main(){final int[] iArr={1,2,3,4};iArr[2]=-3;//合法iArr=null;//非法,对iArr不能重新赋值final Person p = new Person(25);p.setAge(24);//合法p=null;//非法}
}
为什么匿名内部类只能访问局部final变量?
就是比如说假设有一个Test类,然后我们里面创建了一个匿名内部类,而编译之后其实会生成两个class文件,Test.class
和 Test1$.class
而又因为内部类和外部类其实是处于同一个级别的也就是说匿名内部类并不会因为定义在外部类方法之中就会随着方法的执行完毕而被销毁。
所以这就会导致一个问题:当外部类的方法结束的时候,外部类的局部变量就会被销毁,因为随着栈弹出了嘛,但是这时候内部类对象可能还会存在(只是没有人引用它时,才会死亡,但是有可能它的引用通过方法调用被传给其他变量了呀,所以不会死亡)。
所以就出现了一个问题,也就是内部类对象访问了一个不存在的变量,因为那个变量被栈弹出去了。
为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样的话当局部变量死亡之后,内部类仍然可以访问它(实际上访问的是局部变量的"copy")。
而将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的,也就是如果我们在内部类中修改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?
所以就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协。使得局部变量与内部类内建立的拷贝保持一致!!!