我在 Java Puzzlers VI 中发现了一个错误 - 有人能解释一下吗?

发布于 2024-10-10 05:07:32 字数 1288 浏览 0 评论 0原文

看看 Josh Bloch 和 William Pugh 制作的Java 谜题视频,时间索引 0:25:00-0:33:00 左右。

一位发言者说,如果您使用小写的 boolean 而不是 Boolean,那么 LIVING 将被视为真正的“编译时间常量”,并且什么时候初始化就不再重要了。

好吧,这一切都很好,但是,看看当您恢复静态 init 和构造函数之间的原始顺序时会发生什么,然后通过简单的“提取方法”操作来跟进。这两个程序打印不同的输出:

public class Elvis {
    private static final Elvis ELVIS = new Elvis();

    private Elvis () {}
    private static final boolean LIVING = true;
    private final boolean alive = LIVING;
    private final boolean lives () {return alive;}

    public static void main(String[] args) {
        System.out.println(ELVIS.lives()); // prints true
    }
}

使用重构的 returnTrue() 方法

public class Elvis {
    private static final Elvis ELVIS = new Elvis();

    private Elvis () {}
    private static final boolean LIVING = returnTrue();

    private static boolean returnTrue() {
        return true;
    }

    private final boolean alive = LIVING;
    private final boolean lives () {return alive;}

    public static void main(String[] args) {
        System.out.println(ELVIS.lives()); // prints false
    }
}

为什么在这种情况下提取 returnTrue() 方法会改变程序输出?

Take a look at this java puzzles vid by Josh Bloch and William Pugh, around time index 0:25:00-0:33:00.

One of the speakers says that if you use lowercase boolean instead of Boolean, then LIVING will be treated as a true "compile time constant", and it no longer matters when it is initialized.

Well, this is all fine and dandy, but, take a look at what happens when you revert to the original order between the static init and the constructor, and then follow it up by a simple "Extract Method" operation. These two programs print different outputs:

public class Elvis {
    private static final Elvis ELVIS = new Elvis();

    private Elvis () {}
    private static final boolean LIVING = true;
    private final boolean alive = LIVING;
    private final boolean lives () {return alive;}

    public static void main(String[] args) {
        System.out.println(ELVIS.lives()); // prints true
    }
}

And with the refactored returnTrue() method

public class Elvis {
    private static final Elvis ELVIS = new Elvis();

    private Elvis () {}
    private static final boolean LIVING = returnTrue();

    private static boolean returnTrue() {
        return true;
    }

    private final boolean alive = LIVING;
    private final boolean lives () {return alive;}

    public static void main(String[] args) {
        System.out.println(ELVIS.lives()); // prints false
    }
}

Why does extracting the returnTrue() method change the program output in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半葬歌 2024-10-17 05:07:32

您所观察到的行为的关键是“常量变量”的概念。这种矛盾是在 JLS 4.12.4 作为原始类型或 String 类型的变量,它是最终的并使用编译时常量表达式进行初始化。在 JLS 13.1 中,它说引用常量字段在编译时解析为它们表示的常量值(即,它们是内联的)。视频中的谜题依赖于这样一个事实:布尔值既不是基元也不是字符串。您的变体依赖于这样一个事实:在表达式中调用方法 (returnTrue) 可防止其成为编译时常量表达式。无论哪种方式,LIVING 都不是常量变量,程序会显示违反直觉的行为。

Java Puzzlers(《Class Warfare》)中的 Puzzle 93 与之相关,甚至更令人惊讶。

The key to the behavior that you're observing is notion of "constant variable." This oxymoron is defined in JLS 4.12.4 as a variable of primitive type or type String that is final and initialized with a compile-time constant expression. In JLS 13.1, it says that references to constant fields are resolved at compile time to the constant values they denote (i.e., they're inlined). The puzzle in the video relies on the fact that a Boolean is neither a primitive nor a String. Your variant relies on the fact that invoking a method (returnTrue) in an expression prevents it from being a compile-time constant expression. Either way, LIVING is not a constant variable and the program displays the counterintuitive behavior.

Puzzle 93 in Java Puzzlers ("Class Warfare") is related, and even more surprising.

守不住的情 2024-10-17 05:07:32

在第二种情况下,LIVING 由运行时表达式初始化,因此它不再是编译时常量,并且在 ELVIS 运行时其值为 false 已构建。

In the second case LIVING is initialized by the runtime expression, therefore it's not a compile-time constant any more, and its value is false at the time when ELVIS is constructed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文