二、Final关键字 1、修饰的类不能继承 2、修饰的方法不能被重写,能被重载 3、修饰的基本数据类型不可改值,引用类型不可改指向新对象,但可改新对象的值 4、修饰的成员变量,声明赋值or代码块赋值or构造方法赋值;修饰的类/静态变量,声明赋值 or static代码块赋值 5、局部的内部类和匿名内部类只能访问局部的final变量 原因:内部类和外部类是处于同一层级,当外部类的方法执行完毕后,会释放方法里面的局部变量。而局部变量又被内部类使用。 于是会产生一个矛盾:内部类使用已释放的外部类方法里的局部变量。为了解决这个矛盾,内部类copy一份外部类的局部变量作为成员变量。 且为了保证数据一致性,将变量设置为final类型。
/**
* @author :Allen_小鹿
* @date :Created in 2022/1/15 5:16 下午
* @description:final字段测试
*/
/**
* 摘要:Final关键字特性
* 1、修饰的类不能继承
* 2、修饰的方法不能被重写,能被重载
* 3、修饰的基本数据类型不可改值,引用类型不可改指向新对象,但可改新对象的值
* 4、修饰的成员变量,声明赋值or代码块赋值or构造方法赋值;修饰的类/静态变量,声明赋值 or static代码块赋值
* 5、局部的内部类和匿名内部类只能访问局部的final变量
* 原因:内部类和外部类是处于同一层级,当外部类的方法执行完毕后,会释放方法里面的局部变量。而局部变量又被内部类使用。
* 于是会产生一个矛盾:内部类使用已释放的外部类的局部变量。为了解决这个矛盾,内部类copy一份外部类的局部变量作为成员变量。
* 且为了保证数据一致性,将变量设置为final类型。
*
*/
public class FinalTest {
// 1、修饰的类不能被继承
final class FT1 {
}
/*
继承,编译报错!!!
class FT2 extends FT1{
}
*/
// 2、修饰的方法不能被重写,可以重载
class FT3 {
final void run() {
System.out.println("run >>>");
}
// 重载,正常编译!!!
void run(String name) {
System.out.println(name + "run >>>");
}
}
class FT4 extends FT3 {
/*
重写,编译报错!!!
void run() {
super.run();
}
*/
}
// 3、修饰的基本数据类型不可改值,引用数据类型不可指向新的对象,但可以改引用的对象的值
final int c = 10;
final boolean b = false;
/*
改八种基本数据类型,编译报错!!!
c = 20;
b = true;
*/
int d = 10;
public int getD() {
return d;
}
public void setD(int d) {
this.d = d;
}
public static void main(String[] args) {
final FinalTest ft = new FinalTest();
/*
改引用类型指向新对象,编译报错!!!
ft = new FinalTest();
*/
ft.setD(100);
/*
改引用对象的值,编译正常!!!
*/
System.out.println(ft.getD());
ft.test(20);
}
// 4、修饰的成员变量,声明赋值or代码块赋值or构造方法赋值;
// 修饰的类/静态变量,声明赋值 or static代码块赋值
final int i1 = 10;
final int i2;
{
i2 = 20;
}
final int i3;
public FinalTest() {
i3 = 30;
}
final static int j1 = 10;
final static int j2;
static {
j2 = 20;
}
// 5、局部的内部类和匿名内部类只能访问局部的final变量
private int t1 = 10;
void test(int t2) {
int t3 = 30;
class InnerClass {
void test1() {
t1 = 11;
/*
编译报错!!!说明t2和t3很可能是final修饰的,通过反编译class文件证实推测
t2 = 21;
t3 = 31;
*/
System.out.println("innerClass >>>" + t1);
System.out.println("innerClass >>>" + t2);
System.out.println("innerClass >>>" + t3);
}
}
new InnerClass().test1();
new Thread() {
public void run() {
t1 = 12;
/*
编译报错!!!说明t2和t3很可能是final修饰的,通过反编译class文件证实推测
t2 = 21;
t3 = 31;
*/
System.out.println("Thread >>>" + t1);
System.out.println("Thread >>>" + t2);
System.out.println("Thread >>>" + t3);
}
}.start();
}
}
重点:内部类反编译结果显示,内部类使用的 外部类方法里的局部变量 是final修饰的
|