值传递

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

先来看个例子:

public static void valueCross(int age,float weight) {
System.out.println("传入的age值:"+age);
System.out.println("传入的weight值:"+weight);
age=23;
weight=60;
System.out.println("修改后的age值:"+age);
System.out.println("修改后的weight值:"+weight);
} public static void main(String[] args) {
int age=10;
int weight=50;
valueCross(age,weight);
System.out.println("方法执行后的age:"+age);
System.out.println("方法执行后的weight:"+weight); }

  

运行结果:

传入的age值:10
传入的weight值:50.0
修改后的age值:23
修改后的weight值:60.0
方法执行后的age:10
方法执行后的weight:50

  

我们可以看到valueCross方法执行后,实参age和weight的值并没有发生变化,这是什么原因?

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

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

因此这两个age和weight对应的内容不是同一个,在valueCross方法中修改的只是自己栈中的内容,并没有修改main方法栈中的内容

引用传递

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

先有一个Person类代码如下:

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 class TestArr {

	public static void PersonCross(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(4);
PersonCross(p);
System.out.println("方法执行后的name:"+p.getName());
} }

  

测试结果1:

传入的person的name:哪吒
方法内重新赋值后的name:敖丙
方法执行后的name:敖丙

  

我们可以看到PersonCross方法执行后,person的name值被改变了

下面再看一段代码:

public class TestArr {
public static void PersonCross(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(4);
PersonCross(p);
System.out.println("方法执行后的name:"+p.getName());
} }

  

测试结果2:

传入的person的name:哪吒
方法内重新赋值后的name:敖丙
方法执行后的name:哪吒

  

有没有发现什么不同,这次PersonCross方法执行后person的name值并没有改变,这又是为什么?

我们知道,java中的对象和数组是存放在堆内存中的,而堆内存是线程共享的,所以main方法执行时,会在堆内存中开辟一块内存,用来存储p对象的所有内容,然后再栈内存中创建一个引用p存储堆区中p对象的真实地址,如下图:

当执行到PersonCross方法时,因为方法内有这么一行代码:person=new Person(),此时JVM在堆内存中又开辟了一块内存空间,假设地址为xo2222,那么现在的person则指向了xo2222这块内存,现在修改person的name值修改的是xo2222这块内存空间的值,不会改变xo3333的值,所以测试结果2中的name没有发生变化

引用传递本质上就是值传递,将引用变量的值传递给形参,因为引用变量的值存放的是地址值,所以当地址值传递给形参后,形参和实参指向同一块内存区域。

最新文章

  1. 匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的
  2. QuartZ Cron表达式
  3. 2014年年度工作总结--IT狂人实录
  4. 微信:JSSDK开发
  5. Android引导指示层的制作 (ViewStub + SharePreference)
  6. PHP面向对象学习六 多态
  7. Linux第14周学习笔记
  8. [原创]java WEB学习笔记77:Hibernate学习之路---Hibernate 版本 helloword 与 解析,.环境搭建,hibernate.cfg.xml文件及参数说明,持久化类,对象-关系映射文件.hbm.xml,Hibernate API (Configuration 类,SessionFactory 接口,Session 接口,Transaction(事务))
  9. RAID5和RAID10,哪种RAID更适合你(上)
  10. EffectiveC#03--用委托表示回调,用事件定义对外接口
  11. WordPress插件制作教程概述
  12. Parade
  13. HDU1423 LCIS
  14. 【转】Python——读取html的table内容
  15. Arcpy多线程热力图
  16. 浅谈java中的祖先类Object
  17. Shell脚本学习-echo命令
  18. UltraEdit程序设置添加到右键菜单
  19. Phalcon学习-model
  20. CentOS系统命令

热门文章

  1. mysql 对返回的值是null进行判断和重新赋值
  2. Eclipse自动生成作者、日期注释等功能设置 (转载)
  3. 关于Mysql-unknow-column-in-where-clause
  4. 迷你版AOP框架
  5. ifc构件加载到树形控件中
  6. kafka和zookeeper的配置文件优化配置
  7. 对Mysql数据表本身进行操作
  8. Node.jsp配环境更新中)
  9. Centos7彻底删除PHP
  10. 容器版单个jenkins实现CI/CD----带solo博客开源项目