final
final关键字哔哩哔哩
最终的
-
修饰类:表示类不可以被继承
-
修饰方法:表示方法不可被子类覆盖,但是可以重载
-
修饰变量:表示变量一旦被赋值就不可以更改它的值
修饰成员变量
如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定的初始值。
//final修饰的类变量只能有以下两种赋值方式:
public class User{
public int userId;
public final static int Id=2;//类变量ID在声明的时候赋值
pubilc final static int schoolId;//类变量在静态代码块中赋值
static{
schoolId=3;
}
}
如果final修饰的是成员变量,可以在静态代码块、声明时、构造器中赋值。
//final修饰的成员变量比类变量多了一种赋值选择:构造器中赋值
public class People{
public final int id=10;//声明时赋值
public final int age;//静态代码块赋值
static {
age=20;
}
public final int pid;
public People(){
pid=30;//构造器中赋值
}
}
修饰局部变量
系统不会为局部变量进行初始化,局部变量必须有程序员显示的初始化,因此使用final修饰局部变量时,既可以在定义时赋值,也可不再定义时赋值,而在后面的代码中对final变量赋值,不管怎样final修饰的变量都只可以赋值一次,后面不能再修改。
public class Test{
public static void main(String []args){
final int id;//局部变量只声明没有初始化,不会报错,与final无关
id = 2;//在使用final 变量之前一定要初始化
}
}
修饰基本类型数据和引用类型数据
如果是基本数据类型的变量,则其数值一旦初始化后就不能更改。
如果是引用类型变量,则对象初始化一个对象之后,就不能在指向其他的对象,但是引用对象的值可以改变。
public class Person{
final int[] iarr={1,2,3};
iarr[1]=5;//合法
iarr=null//不合法,iarr不能重新赋值,可以理解为iarr是一个地址指针,这个地址指向不能改变,但是可以对指向的地址内的数据进行改变。
public int i;
public Pserson(int i){
this.i=i;
}
final Person person=new Person(5);
person.i=4;//合法的
person=null;//不合法
person=new Person(6);//不合法
}
为什么局部内部类和匿名内部类只能访问局部final变量?
含有内部类的.java 文件,在编译之后会生成两个class文件,Test.class, Test$InnerTest.class(内部类的class文件 注意$后面没有1) Test$1Inclass.class(局部内部类) Test$1.class(匿名内部类)
public class Test{
public Test(){}
public static void main(String []args){}
public class InnerTest{//内部类
public InnerTest(){}
}
public void outPrint(final int x){
class Inclass{//局部内部类
public void InPrint(){
System.out.print(x+1);
}
}
}
final int y=2;
public void setSomething(){
new Thread(){//匿名内部类
public void run(){
System.out.print(y-1);
}
}.start();
}
}
不管是内部类还是非内部类(外部类),他们就是属于同一级别,内部的类不会因为外部类已经执行结束了而结束自己的运行,外部的类和方法可以被回收,内部类没有执行玩就不会被回收。
问题1就出现在这里,当外部类执行完成被销毁了,它的属性(局部变量)也就被销毁了,但是内部类有可能调用了外部类的局部变量。内部类不可能访问一个不存在的局部变量。
解决方法:将外部类中的局部变量复制了一份放进内部类中(一般是看不见的),当局部变量死亡后,内部类任可以访问局部变量的“copy”,这样就好像延长了局部变量的生命周期。
问题2也随之来了,将局部变量复制为内部类的变量时,必须保证两个变量是一样的,也就是如果在内部类中修改了成员变量,方法中的局部变量也要跟着改变,这怎么解决?
解决方法:将内部类使用的外部局部变量设置为final,这样这个变量就一定能保持一致了,内部类不能改变这个局部变量了。这样就是为什么局部内部类和匿名内部类只能访问final修饰的局部变量