java 嵌套赋值和普通赋值有什么区别吗?

lymnna71  于 2023-05-12  发布在  Java
关注(0)|答案(2)|浏览(122)

我有个准则

final int a, b;
a = b = 10;

while (a <= b) {
    System.out.println("this is in while loop");
}
System.out.println("this is out of while loop");

在本例中,我的while块执行了无限次。
在有另一个代码

final int a=10;
final int b = 10;

while (a <= b) {
    System.out.println("this is in while loop");
}
System.out.println("this is out of while loop");

在这种情况下,我得到编译错误,提到while循环外的语句代码不可达
即使它们是最终变量。我试图在这两种情况下分别重新分配变量a和b的值,但我不能在这两种情况下重新分配值,因为它是最终变量。但是在我提到的第一种情况下,它们不被认为是常数,这是循环重复的原因。

xqk2d5yq

xqk2d5yq1#

虽然在两种情况下变量都是final,但第二种情况下的变量也是 * 常量变量 *:
常量变量是原始类型或String类型的最终变量,它用常量表达式初始化(§15.29)。一个变量是否是常量变量可能会影响[...]可达性(§14.22)[...]。
第一种情况下的变量不是常量变量,因为它们没有初始化。它们在下一个语句中赋值。注意final变量不需要初始化=它们只需要是definitely assigned
这使得第二个代码中的a <= b成为一个 * 常量表达式 *,其常量值为true。这会影响一个语句是否 * 可达 *。请参阅本节中的相关引文。
如果某个语句由于不可访问而无法执行,则这是一个编译时错误。
非空块中的第一个语句是可达的,当且仅当该块是可达的。
非空块中的每一个语句S都是可达的,当且仅当S前面的语句可以正常完成。

  • while语句可以正常完成,前提是至少满足以下条件之一:
  • while语句是可达的,条件表达式不是值为true的常量表达式(第15.29节)。
  • 有一个退出while语句的可到达break语句。

在这种情况下,由于while语句确实有一个常量true条件,并且没有break s,因此while语句无法正常完成。这会导致while循环后的语句不可访问。

agyaoht7

agyaoht72#

我用一种不专业的方式来解释这个现象,测试类如下:

package com;                                                                                                       
                                                                                                                   
public class Assignment {                                                                                          
    public static void main(String[] args) { }                                                                           
    public int m1() {                                                           
        final int a, b;                                                         
        a = b = 10;                                                             
        return a + b;                                                                                              
    }                                                                           
    public int m2() {                                                           
        int a, b;                                                               
        a = b = 10;                                                             
        return a + b;                                                                                              
    }                                                                                                              
    public int m3() {                                                           
        final int a = 10;                                                                                          
        final int b = 10;                                                       
        return a + b;                                                           
    }                                                                           
}

用javac编译后,用javap反编译的结果如下:

Compiled from "Assignment.java"
public class com.Assignment {
  public com.Assignment();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: return

  public int m1();
    Code:
       0: bipush        10
       2: dup
       3: istore_2
       4: istore_1
       5: iload_1
       6: iload_2
       7: iadd
       8: ireturn

  public int m2();
    Code:
       0: bipush        10
       2: dup
       3: istore_2
       4: istore_1
       5: iload_1
       6: iload_2
       7: iadd
       8: ireturn

  public int m3();
    Code:
       0: bipush        20
       2: ireturn
}

注意m3,return的值直接换成20!
计算m1和m2两者,即特定值 直到运行阶段才知道。
因此,可以得出下一个结论,m3中的值实际上可以在编译阶段确定。如果将它作为条件放入while中,则可以在编译阶段知道结果。

相关问题