final 在 Java 中有什么作用?
final 修饰的类叫最终类,该类不能被继承。
final 修饰的方法不能被重写。
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
(1) 修饰成员变量
成员变量涉及到初始化的问题,只能二选一。(显示初始化、构造方法初始化)。
由于成员变量具有默认值,用final之后必须手动赋值,不会再给默认值了;对于final的成员变量,要么直接赋值,要么通过构造方法赋值)
public class YuYio {
private final String name;
public YuYio(){
name="丽丽";//构造方法手动赋值
}
public YuYio(String name) {
this.name = name;
}
public String getName() {
return name;
}
-
如果修饰的是
类变量
,只能在静态初始化快中制定初始值
或者声明该类变量指定
该类变量指定初始值 -
如果修饰的是
成员变量
,可以在非静态初始化块
、声明该变量
或者构造器
中执行初始值
(2) 修饰局部变量
系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。因为使用 final修饰局部变量时,既可以在 定义时指定默认值( 后面的代码不能对变量再赋值),也可以不指定默认值,而在后面的代码中对 final 变量赋初值(仅一次)
public class Test {
final static String a = '测试';//再声明的时候需要赋值 或者静态代码块赋值
/**
static {
String a = '测试';
}
*/
final String b = '尝试';//再声明的时候需要赋值 或者代码块中赋值 或者构造器赋值
/*
b = '尝试';
*/
public static void main(String[] args){
final String Aa;//局部变量只声明没有初始化,不会报错,与fina无关
Aa = '测试';//在使用之前一定要赋值
//Aa = '再测试' 但是不允许第二次赋值
}
}
(3) 修饰基本类型数据和引用类型数据
修饰基本类型:只能赋值一次,不能再更改。(不可变的是变量的数据
不能进行更改)
修饰引用类型:只能指向一个对象,地址不能再改,但是不能修改。(不可变的是变量的地址
不能进行更改)
public class Pesron {
private int age;
public Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args){
final int [] i = {1,2,3,4};
i[2] = -1;//正确
i= null; //错误,不能对i重新赋值
final Person p = new Person (25);
p.setAge(24);//正确
p=null;//错误
}
}
为什么局部类和匿名内部类只能访问局部 final 变量
首先需要知道的一点是: 内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。
这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还得在(只有没有人再引用它时,才会死亡),这里就出现了一个矛盾:内部类对像访问了一个不存在的变量,为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的"copy”。这样就好像延长了局部变量的生命周期
局部变量复制为内部类的成员交量时,必须保让这两个变量是一样的,也就是如果我们在内部类中你改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?
就将局部变量设置为null,对它初始化吼,就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一数性。这实际上也是一种妥协,使得局部变量与内部支类建立的拷贝保持一致。