(四.2)值传递和引用传递

转自:https://juejin.im/post/5bce68226fb9a05ce46a0476

在对(四.1)JVM内存的划分及职能 简单理解后,解释值传递和引用传递

值传递:


在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。

public static void valueCrossTest(int age,float weight){ 
  System.out.println("传入的age:"+age); 
  System.out.println("传入的weight:"+weight);  
  age=33;
  weight=89.5f;
  System.out.println("方法内重新赋值后的age:"+age); 
  System.out.println("方法内重新赋值后的weight:"+weight); 
 } 

 public static void main(String[] args) {
      int a=25;
      float w=77.5f;
      valueCrossTest(a,w);
      System.out.println("方法执行后的age:"+a);
     System.out.println("方法执行后的weight:"+w);
}

输出结果:

传入的age:25
传入的weight:77.5

方法内重新赋值后的age:33
方法内重新赋值后的weight:89.5

方法执行后的age:25
方法执行后的weight:77.5

下面我们根据上面学到的知识点,进行详细的分析:

首先程序运行时,调用mian()方法,此时JVM为main()方法往虚拟机栈中压入一个栈帧,即为当前栈帧,用来存放main()中的局部变量表(包括参数)、操作栈、方法出口等信息,如a和w都是mian()方法中的局部变量,因此可以断定,a和w是躺着mian方法所在的栈帧中

而当执行到valueCrossTest()方法时,JVM也为其往虚拟机栈中压入一个栈,即为当前栈帧,用来存放valueCrossTest()中的局部变量等信息,因此age和weight是躺着valueCrossTest方法所在的栈帧中,而他们的值是从a和w的值copy了一份副本而得,如图:

因而可以a和age、w和weight对应的内容是不一致的,所以当在方法内重新赋值时,实际流程如图:

也就是说,age和weight的改动,只是改变了当前栈帧(valueCrossTest方法所在栈帧)里的内容,当方法执行结束之后,这些局部变量都会被销毁,mian方法所在栈帧重新回到栈顶,成为当前栈帧,再次输出a和w时,依然是初始化时的内容。
因此:
值传递传递的是真实内容的一个副本,对副本的操作不影响原内容,也就是形参怎么变化,不会影响实参对应的内容。

 

引用传递:


”引用”也就是指向真实内容(对象)的地址值,在方法调用时,实参的地址通过方法调用被传递给相应的形参,在方法体内,形参和实参指向同一块内存地址,对形参的操作会影响的真实内容。

public class Person {
   private String name;
   private int age; 
   public String getName() { 
     return name;
     } 
  public void setName(String name) 
  {   this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;   
  }
}


我们写个函数测试一下:

 public static void PersonCrossTest(Person person){ 
      System.out.println("传入的person的name:"+person.getName()); 
    
      person.setName("我是张小龙"); 
      System.out.println("方法内重新赋值后的name:"+person.getName());
      } 

public static void main(String[] args) { 
   Person p=new Person(); 
   p.setName("我是马化腾");
   p.setAge(45);
   PersonCrossTest(p);
   System.out.println("方法执行后的name:"+p.getName());
}

输出:

传入的person的name:我是马化腾
方法内重新赋值后的name:我是张小龙
方法执行后的name:我是张小龙

稍加修改:

 public static void PersonCrossTest(Person person){ 
      System.out.println("传入的person的name:"+person.getName()); 
      person=new Person();  //新增代码
      person.setName("我是张小龙"); 
      System.out.println("方法内重新赋值后的name:"+person.getName());
      } 

public static void main(String[] args) { 
   Person p=new Person(); 
   p.setName("我是马化腾");
   p.setAge(45);
   PersonCrossTest(p);
   System.out.println("方法执行后的name:"+p.getName());
}
传入的person的name:我是马化腾
2方法内重新赋值后的name:我是张小龙
3方法执行后的name:我是马化腾

发布了548 篇原创文章 · 获赞 88 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/jiangshangchunjiezi/article/details/96372491