gpt4 book ai didi

java - 有效地最终与最终 - 不同的行为

转载 作者:行者123 更新时间:2023-12-01 23:10:43 28 4
gpt4 key购买 nike

到目前为止,我认为 有效最终 最后 或多或少是等效的,如果在实际行为中不相同,JLS 会将它们视为相似。然后我发现了这个人为的场景:

final int a = 97;
System.out.println(true ? a : 'c'); // outputs a

// versus

int a = 97;
System.out.println(true ? a : 'c'); // outputs 97
显然,JLS 在这里两者之间产生了重要区别,我不知道为什么。
我阅读了其他主题,例如
  • Difference between final and effectively final
  • Effectively final variable vs final variable
  • What does a variable being “effectively final” mean?

  • 但他们没有详细说明。毕竟,在更广泛的层面上,它们似乎几乎是等价的。但深入挖掘,它们显然不同。
    是什么导致了这种行为,谁能提供一些解释这一点的 JLS 定义?

    编辑:我发现了另一个相关的场景:
    final String a = "a";
    System.out.println(a + "b" == "ab"); // outputs true

    // versus

    String a = "a";
    System.out.println(a + "b" == "ab"); // outputs false
    所以字符串实习在这里的行为也不同(我不想在实际代码中使用这个片段,只是对不同的行为感到好奇)。

    最佳答案

    首先,我们说的是局部变量 只有。实际上 final 不适用于字段。这很重要,因为 final 的语义字段非常不同,并且受到大量编译器优化和内存模型 promise 的影响,请参阅 $17.5.1关于 final 字段的语义。
    在表面上 finaleffectively final因为局部变量确实是相同的。但是,JLS 对两者进行了明确区分,这在这种特殊情况下实际上具有广泛的影响。

    前提
    来自 JLS§4.12.4关于 final变量:

    A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.29). Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1), reachability (§14.22), and definite assignment (§16.1.1).


    int是原始的,变量 a是这样的 常量变量 .
    此外,来自同一章关于 effectively final :

    Certain variables that are not declared final are instead considered effectively final: ...


    因此,从措辞方式来看,很明显,在另一个示例中, a不是 被认为是一个常数变量,因为它是 不是最终的 ,但只是有效地最终。

    行为
    现在我们有了区别,让我们看看发生了什么以及为什么输出不同。
    您正在使用条件运算符 ? :在这里,所以我们必须检查它的定义。来自 JLS§15.25 :

    There are three kinds of conditional expressions, classified according to the second and third operand expressions: boolean conditional expressions, numeric conditional expressions, and reference conditional expressions.


    在这种情况下,我们谈论的是 数值条件表达式 ,来自 JLS§15.25.2 :

    The type of a numeric conditional expression is determined as follows:


    这就是两种情况分类不同的部分。
    有效地最终
    版本是 effectively final与此规则匹配:

    Otherwise, general numeric promotion (§5.6) is applied to the second and third operands, and the type of the conditional expression is the promoted type of the second and third operands.


    这与您所做的行为相同 5 + 'd' ,即 int + char ,结果是 int .见 JLS§5.6

    Numeric promotion determines the promoted type of all the expressions in a numeric context. The promoted type is chosen such that each expression can be converted to the promoted type, and, in the case of an arithmetic operation, the operation is defined for values of the promoted type. The order of expressions in a numeric context is not significant for numeric promotion. The rules are as follows:

    [...]

    Next, widening primitive conversion (§5.1.2) and narrowing primitive conversion (§5.1.3) are applied to some expressions, according to the following rules:

    In a numeric choice context, the following rules apply:

    If any expression is of type int and is not a constant expression (§15.29), then the promoted type is int, and other expressions that are not of type int undergo widening primitive conversion to int.


    所以一切都被提升到 intaint已经。这解释了 97 的输出.
    final
    版本与 final变量与此规则匹配:

    If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.29) of type int whose value is representable in type T, then the type of the conditional expression is T.


    最终变量 a类型为 int和一个常量表达式(因为它是 final )。它可以表示为 char ,因此结果的类型是 char .结果输出 a .

    字符串示例
    字符串相等的示例基于相同的核心差异, final变量被视为常量表达式/变量,并且 effectively final不是。
    在 Java 中, 字符串实习 基于常量表达式,因此
    "a" + "b" + "c" == "abc"
    true以及(不要在实际代码中使用此构造)。
    JLS§3.10.5 :

    Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.29) - are "interned" so as to share unique instances, using the method String.intern (§12.5).


    容易被忽视,因为它主要讨论的是文字,但它实际上也适用于常量表达式。

    关于java - 有效地最终与最终 - 不同的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63738711/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com