【java基础】为何e1==(e1=e2)为false

 

代码如下

public class Exercise {
	
	static void print(Exercise e1,Exercise e2) {
		System.out.println(e1==(e1=e2));
	}
	public static void main(String[] args) {
		Exercise e1 = new Exercise();
		Exercise e2 = new Exercise();
		print(e1,e2);
	}
}

编译后,使用javap 查看字节码

javap -verbose Exercise.class

参考指令:https://cs.au.dk/~mis/dOvs/jvmspec/ref-Java.html

可以看出, 5行的时候,将第二个局部变量压入两次。

6行的时候,弹出栈顶局部变量。 导致之后比较的时候,栈顶的两个引用不相同。 因此输出false.

 

相关指令

  • 0x59 dup 复制栈顶数值并将复制值压入栈顶
  • 0x19 aload 将指定的引用类型本地变量推送至栈顶
  • 0x3a astore 将栈顶引用类型数值存入指定本地变量
  • 0xa0 if_icmpne 比较栈顶两int型数值大小, 当结果不等于0时跳转
  • 0xb6 invokevirtual 调用实例方法

 

相关字节码

D:\temp\test>javap -verbose Exercise.class
Classfile /D:/temp/test/Exercise.class
  Last modified 2019-2-12; size 569 bytes
  MD5 checksum ca83d3f8fc84d49a8e6cec7faeb7b527
  Compiled from "Exercise.java"
public class Exercise
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #7.#21         // java/lang/Object."<init>":()V
   #2 = Fieldref           #22.#23        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #24.#25        // java/io/PrintStream.println:(Z)V
   #4 = Class              #26            // Exercise
   #5 = Methodref          #4.#21         // Exercise."<init>":()V
   #6 = Methodref          #4.#27         // Exercise.print:(LExercise;LExercise;)V
   #7 = Class              #28            // java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               print
  #13 = Utf8               (LExercise;LExercise;)V
  #14 = Utf8               StackMapTable
  #15 = Class              #29            // java/io/PrintStream
  #16 = Class              #26            // Exercise
  #17 = Utf8               main
  #18 = Utf8               ([Ljava/lang/String;)V
  #19 = Utf8               SourceFile
  #20 = Utf8               Exercise.java
  #21 = NameAndType        #8:#9          // "<init>":()V
  #22 = Class              #30            // java/lang/System
  #23 = NameAndType        #31:#32        // out:Ljava/io/PrintStream;
  #24 = Class              #29            // java/io/PrintStream
  #25 = NameAndType        #33:#34        // println:(Z)V
  #26 = Utf8               Exercise
  #27 = NameAndType        #12:#13        // print:(LExercise;LExercise;)V
  #28 = Utf8               java/lang/Object
  #29 = Utf8               java/io/PrintStream
  #30 = Utf8               java/lang/System
  #31 = Utf8               out
  #32 = Utf8               Ljava/io/PrintStream;
  #33 = Utf8               println
  #34 = Utf8               (Z)V
{
  public Exercise();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  static void print(Exercise, Exercise);
    descriptor: (LExercise;LExercise;)V
    flags: ACC_STATIC
    Code:
      stack=4, locals=2, args_size=2
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStrea
         3: aload_0
         4: aload_1
         5: dup
         6: astore_0
         7: if_acmpne     14
        10: iconst_1
        11: goto          15
        14: iconst_0
        15: invokevirtual #3                  // Method java/io/PrintStream.println:(Z)V
        18: return
      LineNumberTable:
        line 6: 0
        line 7: 18
      StackMapTable: number_of_entries = 2
        frame_type = 78 /* same_locals_1_stack_item */
          stack = [ class java/io/PrintStream ]
        frame_type = 255 /* full_frame */
          offset_delta = 0
          locals = [ class Exercise, class Exercise ]
          stack = [ class java/io/PrintStream, int ]

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: new           #4                  // class Exercise
         3: dup
         4: invokespecial #5                  // Method "<init>":()V
         7: astore_1
         8: new           #4                  // class Exercise
        11: dup
        12: invokespecial #5                  // Method "<init>":()V
        15: astore_2
        16: aload_1
        17: aload_2
        18: invokestatic  #6                  // Method print:(LExercise;LExercise;)V
        21: return
      LineNumberTable:
        line 10: 0
        line 11: 8
        line 12: 16
        line 13: 21
}
SourceFile: "Exercise.java"

PS:个人理解,欢迎指正。

参考

JVM 虚拟机字节码指令表

Java Virtual Machine Online Instruction Reference

posted @ 2019-02-12 18:22  thewindkee  阅读(238)  评论(0编辑  收藏  举报