Java 运算符优先级示例

Java Operator Precedence example

我知道Operator Precedence list,但我无法弄清楚“LINE 1”中这段代码的执行优先级是多少。之前创建了什么对象?例如:My String 还是 new Precedence()?我们如何在此示例中应用运算符优先级规则?

public class Precedence {
    public String s;
    public static void main (String ... args){
        String a = new Precedence().s="My String"; // LINE 1
        System.out.println(a);
    }
}

输出: My String

这是字节码:

public static transient varargs main([Ljava/lang/String;)V
   L0
    LINENUMBER 8 L0
    NEW Precedence
    DUP
    INVOKESPECIAL Precedence.<init> ()V
    LDC "My String"
    DUP_X1
    PUTFIELD Precedence.s : Ljava/lang/String;
    ASTORE 1

这显示了以下执行顺序:

  1. 创建 Precedence 对象。
  2. My String 常量分配给 Precedence.s
  3. 也将其分配给 a

这个

String a = new Precedence().s="My String"; // LINE 1

是一个带有初始化表达式的local variable declaration statement

Every time it is executed, the declarators are processed in order from left to right. If a declarator has an initializer, the initializer is evaluated and its value is assigned to the variable.

a 是声明符。它被评估为产生一个变量(本身)。然后计算初始化表达式。

这个

new Precedence().s = "My String";

an assignment expression。首先计算运算符的左侧以生成变量,因此首先计算 new Precedence(),实例化 class Precedence,生成对对象的引用。然后评估赋值的右侧,即 String 文字 "My String",因此会生成对 String 对象的引用。然后赋值发生,将对 String 对象的引用赋给新实例创建表达式返回的值引用的对象的变量 s

最后,由于

At run time, the result of the assignment expression is the value of the variable after the assignment has occurred.

分配给 Precedence 对象的字段 s 的值也分配给变量 a.

有工具javap, dissassembler,它会向你展示字节码,从那里你可以得出什么是执行顺序。它会输出评论。

$ /usr/lib/jvm/java-7-oracle/bin/javap -c Precedence.class 
Compiled from "Precedence.java"
public class Precedence {
  public java.lang.String s;

  public Precedence();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String...);
    Code:
       0: new           #2                  // class Precedence
       3: dup           
       4: invokespecial #3                  // Method "<init>":()V
       7: ldc           #4                  // String My String
       9: dup_x1        
      10: putfield      #5                  // Field s:Ljava/lang/String;
      13: astore_1      
      14: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
      17: aload_1       
      18: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      21: return        
}

javap 是 JDK 的一部分,路径在 Linux 上,开关 -c 是反汇编代码。这是指令 ldc 的定义,它的作用并不明显

push a constant #index from a constant pool (String, int or float) onto the stack