方法中对传入参数的修改对参数对象的影响

public class Test{
	public static void main(String[] arg){
		Person aaaaaaaaaaaaa = new Person();
		change(aaaaaaaaaaaaa);
	}
	
	public static void change(Person p)
	{
		p.name = "mao";
	}
}

public class Person{
	String name;
}

 对上面Test编译产生如下java指令

Classfile /F:/Test.class
  Last modified 2017-5-26; size 419 bytes
  MD5 checksum b3b57626cd3396f8e3ce811d3b6a54ee
  Compiled from "Test.java"
public class Test
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #8.#19         // java/lang/Object."<init>":()V
   #2 = Class              #20            // Person
   #3 = Methodref          #2.#19         // Person."<init>":()V
   #4 = Methodref          #7.#21         // Test.change:(LPerson;)V
   #5 = String             #22            // mao
   #6 = Fieldref           #2.#23         // Person.name:Ljava/lang/String;
   #7 = Class              #24            // Test
   #8 = Class              #25            // java/lang/Object
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               main
  #14 = Utf8               ([Ljava/lang/String;)V
  #15 = Utf8               change
  #16 = Utf8               (LPerson;)V
  #17 = Utf8               SourceFile
  #18 = Utf8               Test.java
  #19 = NameAndType        #9:#10         // "<init>":()V
  #20 = Utf8               Person
  #21 = NameAndType        #15:#16        // change:(LPerson;)V
  #22 = Utf8               mao
  #23 = NameAndType        #26:#27        // name:Ljava/lang/String;
  #24 = Utf8               Test
  #25 = Utf8               java/lang/Object
  #26 = Utf8               name
  #27 = Utf8               Ljava/lang/String;
{
  public Test();
    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 1: 0
		
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class Person
         3: dup
         4: invokespecial #3                  // Method Person."<init>":()V
         7: astore_1
         8: aload_1
         9: invokestatic  #4                  // Method change:(LPerson;)V
        12: return
      LineNumberTable:
        line 3: 0
        line 4: 8
        line 5: 12

  public static void change(Person);
    descriptor: (LPerson;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: ldc           #5                  // String mao
         3: putfield      #6                  // Field Person.name:Ljava/lang/St
ring;
         6: return
      LineNumberTable:
        line 9: 0
        line 10: 6
}

 第一:我们看不到任何的“aaaaaaaaa”变量名的影子,因为这个变量其实就是一个内存地址,变量名是为了程序员好操作这块地址,而任何对这个地址存储数据的操作编译器都能找到对应地址。

第二:astore_1表示将栈顶引用型数值存入第二个本地变量,aload_1意思是将第二个引用类型本地变量推送至栈顶,也就是把存在第二个本地变量中的指向堆中新建Person对象的地址放到栈顶,change方法第一个指令就是aload_0(将第一个引用类型变量置于栈顶),所以change方法中的p.name="mao"就是修改堆中的新建person对象,main方法中的变量“aaaaaaaaa”指向同一个对象就受影响

但是如果change方法内是p = new Person()那就是方法的第一个引用类型变量指向另一个person对象,main中的“aaaaaaaa”变量就无所谓了

猜你喜欢

转载自xiaoxiaoher.iteye.com/blog/2376537
今日推荐