为什么匿名内部类引用外部局部变量必须要加 final 关键字
Java 面试 About 1,574 wordsJava 代码
public class Test {
public static void main(String[] args) {
final int x = 10;
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(x);
}
};
}
}
匿名内部类
匿名内部类Test$1.class
反编译后的代码。
可以看到:匿名内部类引用外部局部变量是其实是通过生成了一个Test$1
类,构造函数中传递了外部的变量,所以不能更改。
class Test$1 implements Runnable {
final int val$x;
Test$1(final int val$x) {
this.val$x = var1;
}
public void run() {
System.out.println(this.val$x);
}
}
字节码
// class version 52.0 (52)
// access flags 0x20
class com/example/Test$1 implements java/lang/Runnable {
// compiled from: Test.java
OUTERCLASS com/example/Test main ([Ljava/lang/String;)V
// access flags 0x0
INNERCLASS com/example/Test$1 null null
// access flags 0x1010
final synthetic I val$x
// access flags 0x0
<init>(I)V
// parameter final synthetic val$x
L0
LINENUMBER 7 L0
ALOAD 0
ILOAD 1
PUTFIELD com/example/Test$1.val$x : I
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/example/Test$1; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1
public run()V
L0
LINENUMBER 10 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 0
GETFIELD com/example/Test$1.val$x : I
INVOKEVIRTUAL java/io/PrintStream.println (I)V
L1
LINENUMBER 11 L1
RETURN
L2
LOCALVARIABLE this Lcom/example/Test$1; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
}
Views: 1,218 · Posted: 2022-05-17
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...