class A {
    final int a;
    A () {
        this.a = 1; // No error
    }
}

鉴于下面的代码

class A {
    final int a;
    A () {
        A.this.a = 1; // Error: java: cannot assign a value to final variable a
    }
}

使用this.a为最终字段赋值可以很好地工作.但是,使用A.this.a为最终字段赋值会给出错误"Java:无法为最终变量a赋值".不知道为什么?

我明白在这种情况下没有理由显式地使用A.this.a而不是this.a.只是想弄明白原因.

推荐答案

从这个bug report开始,JVM架构师John Rose提到,空白的最终字段(例如,代码中的a)的确定赋值(DA)只通过简单的名称athis.a来跟踪.在确定字段是否明确赋值时,不会考虑其他更复杂的表达式,如A.this.a.

在本例中,(比尔·喜悦和我,IIRC,回到Java 1.1次)做出了相当随意的 Select ,通过跟踪裸字段名"x"或简单限定字段名"this.x"的使用来执行空的最终非静态字段初始化的静态判断,而不是通过其他更复杂的表达式.换句话说,这个"错误"是JLS设计中的一个故意特性.

他进一步解释了理由:

我们希望只允许裸字段名"x"参与DU/DA的静态分析;这将是DU/DA规则的最简单表述.我们恰好添加了"this.x"作为替代,以尊重将构造函数参数和字段命名为相同名称的合理做法(Java记录证实了这种做法).

但保持DU/DA跟踪的这些名称尽可能简单是很重要的,因为它们已经足够复杂,以至于编译器必须训练用户(带有像这个错误报告的错误消息)如何保持在DU/DA的正确性范围内.随意添加DU/DA处理的更复杂的名称语法,会增加本已难以预测的分析的复杂性.尤其是,它使代码更难阅读和在心理上验证.

简而言之,这是一个武断的 Select .他们把地方检察官的规定保持得很简单.

Java相关问答推荐

Jooq隐式地将bigint转换为数字,并且索引不起作用

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

在for—each循环中的AnimationTimer中的if语句'

Java中如何根据Font.canDisplay方法对字符串进行分段

Exe4j创建的应用程序无法再固定在任务栏Windows 11上

DTO到实体,反之亦然,控制器和服务之间的哪一层应该处理转换?

内存中的H2修剪尾随空格

JavaFX如何在MeshView中修复多个立方体?

如何创建模块信息类文件并将其添加到JAR中?

将stringBuilder + forloop转换为stream + map

为什么相同的数据条码在视觉上看起来不同?

在Java中将.GRF转换为图像文件

Java KeyListener不工作或被添加

在Spring Boot中使用咖啡因进行缓存-根据输出控制缓存

从字节数组切换到JakartaMail org.springframework.mail.javamail.JavaMailSender InputStreamResource

由于可为null,无法在kotlin中实现java接口

在数组中查找素数时出现逻辑错误

spring 数据Elastic search 与 spring 启动数据Elastic search 之间的区别是什么?

如何从指定某些字段的父对象创建子对象

Spring Boot应用程序中的自定义constraintvalidator不会被调用