为什么匿名内部类引用外部局部变量必须要加 final 关键字
Java 面试 评论 1 大约 1574 字Java 代码
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
}
阅读 888 · 发布于 2022-05-17
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb扫描下方二维码关注公众号和小程序↓↓↓
昵称:
-
fHLvlxbf 1楼
e
Chrome | Windows 10 2023-07-24
随便看看
换一批
-
Elasticsearch GET/PUT/DELETE/HEAD 指令阅读 2253
-
Windows WSL 下 Docker 启动报 waiting for init preliminary setup caused: EOF: unknown 错误阅读 3953
-
Docker 部署 cAdvisor阅读 3160
-
单例双重校验为什么还要加 volatile阅读 956
-
Android 每隔一分钟发出时间更新广播阅读 5282
-
软考-系统架构设计师:IPv6阅读 2678
-
Spring Boot 无法写出 Cookie阅读 2983
-
Linux 查看进程启动时的命令行参数阅读 593
-
Windows 使用 chcp 修改 PowerShell、cmd 编码阅读 5725
-
Kubernetes kubectl logs -f 过滤关键日志阅读 1843