java参数有值类型和引用类型两种。所以java参数的传值也就从这两个方面分析。
从内存模型来说参数传递更为直观一些,这里涉及到两种类型的内存:栈内存(stack)和堆内存(heap)。
 
基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。
引用类型作为参数传递时,传递的是引用地址。所以在改变引用类型的值时,原值会改变。(String类型特殊,单独说)

基本类型作为参数传递

基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。

代码如下:

 public class ParameterTransfer {
public static void main(String[] args) {
int num = 30;
System.out.println("调用add方法前num=" + num);
add(num);
System.out.println("调用add方法后num=" + num);
} public static void add(int param) {
param = 100;
}
}

代码的运行结果如下:

调用add方法前num=30
调用add方法后num=30
num的值在运行add()方法前后值并未改变,为什么呢?
当执行了int num = 30;这句代码后,程序在栈内存中开辟了一块地址为AD8500的内存,里边放的值是30,内存模型如下图:

执行到add()方法时,程序在栈内存中又开辟了一块地址为AD8600的内存,将num的值30传递进来,此时这块内存里边放的值是30,执行param = 100;后,AD8600中的值变成了100。内存模型如下图:

引用类型作为参数传递

引用类型作为参数传递时,传递的是引用地址。所以在改变引用类型的值时,原值会改变

代码如下:

  public class ParameterTransfer {
public static void main(String[] args) {
String[] array = new String[] {"huixin"};
System.out.println("调用reset方法前array中的第0个元素的值是:" + array[0]);
reset(array);
System.out.println("调用reset方法后array中的第0个元素的值是:" + array[0]);
} public static void reset(String[] param) {
param[0] = "hello, world!";
} }

运行的结果如下:

调用reset方法前array中的第0个元素的值是:huixin
调用reset方法后array中的第0个元素的值是:hello, world!

当程序执行了String[] array = new String[] {"huixin"}后,程序在栈内存中开辟了一块地址编号为AD9500内存空间,用于存放array[0]的引用地址,里边放的值是堆内存中的一个地址,示例中的值为BE2500,可以理解为有一个指针指向了堆内存中的编号为BE2500的地址。堆内存中编号为BE2500的这个地址中存放的才是array[0]的值:huixin。

当程序进入reset方法后,将array的值,也就是对象的引用BE2500传了进来。这时,程序在栈内存中又开辟了一块编号为AD9600的内存空间,里边放的值是传递过来的值,即AD9600。可以理解为栈内存中的编号为AD9600的内存中有一个指针,也指向了堆内存中编号为BE2500的内存地址,如图所示:
这样一来,栈内存AD9500和AD9600(即array[0]和param的值)都指向了编号为BE2500的堆内存。
在reset方法中将param的值修改为hello, world!后,内存模型如下图所示:

改变对象param的值实际上是改变param这个栈内存所指向的堆内存中的值。param这个对象在栈内存中的地址是AD9600,里边存放的值是BE2500,所以堆内存BE2500中的值就变成了hello,world!。程序放回main方法之后,堆内存BE2500中的值仍然为hello,world!,main方法中array[0]的值时,从栈内存中找到array[0]的值是BE2500,然后去堆内存中找编号为BE2500的内存,里边的值是hello,world!。所以main方法中打印出来的值就变成了hello,world!
无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。第一个示例中用基本类型作为参数传递时,将栈内存中的值30传递到了add方法中。第二个示例中用对象作为参数传递时,将栈内存中的值BE2500传递到了reset方法中。当用对象作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,所以传递的就是堆内存的地址。这就是它们的区别。
注意:在Java中,String是一个引用类型,但是在作为参数传递的时候表现出来的却是基本类型的特性,即在方法中改变了String类型的变量的值后,不会影响方法外的String变量的值。原因可能有以下两个:
  • 一个是String实际上操作的是char[],可以理解为String是char[]的包装类。
  • 二是给String变量重新赋值后,实际上没有改变这个变量的值,而是重新new了一个String对象,改变了新对象的值,所以原来的String变量的值并没有改变。

参考文章:http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html

java参数传值方式的更多相关文章

  1. Java中的参数传值方式

    本文转载自 https://blog.csdn.net/SEU_Calvin/article/details/70089977 1.  你觉得下面程序会输出什么 public static void  ...

  2. java中传值方式的个人理解

    前言 这几天在整理java基础知识方面的内容,对于值传递还不是特别理解,于是查阅了一些资料和网上相关博客,自己进行了归纳总结,最后将其整理成了一篇博客. 值传递 值传递是指在调用函数时将实际参数复制一 ...

  3. Java方法 传值方式

    这个问题是面试的时候经常会问到的一道题吧?这次做项目的过程中,其中一个同学因为无用了,导致了一个bug,不过是在提测前啦!本来我想借着这次机会分享一下java方法传参的机制,但是经过几天的学习,了解, ...

  4. java 参数传值

    基本数据类型参数的传值,参数为基本数据类型 class Computer{ int add(int x,int y){ return x+y; } } public class Example4_6 ...

  5. Java参数传值?or传引用?

    O'Reilly's Javain a Nutshell by David Flanagan (see Resources) puts it best: "javamanipulates o ...

  6. Java | 参数传值机制

    值传递 java中,方法中所有的参数的都是"值传递",就是传递的是原来值的副本,不是原来的参数,因此,改变不会影响到原来的参数. 基本数据类型参数的传值 传递的都是副本,改变以后不 ...

  7. 几句话弄清楚Java参数传值还是传引用

    最近刷题做了一些算法题,对于在递归函数调用的时候什么时候传入值,什么时候传入引用有疑问,在网上搜索了一下,得出了一下三条总结: 1.对象就是传引用 2.原始类型就是传值 3.String,Intege ...

  8. 【java】的传值方式

    [java]的传值方式 当你问大多数程序员Java是传值还是传引用的时候,你可能会得到两种答案之一: (1)Java传递原始类型数据时使用的是传值方式:传递对象时则使用传引用方式:String类型的数 ...

  9. C++ //拷贝构造函数调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象 //2.值传递的方式给函数参数传值 //3.值方式返回局部对象

    1 //拷贝构造函数调用时机 2 3 4 #include <iostream> 5 using namespace std; 6 7 //1.使用一个已经创建完毕的对象来初始化一个新对象 ...

随机推荐

  1. iOS自动化环境搭建——macaca

    macaca-java for ios 自动化环境搭建 基础原理解析:https://testerhome.com/topics/6608 一.环境搭建 1.安装eclipse; -----Java开 ...

  2. 我的第一个python web开发框架(8)——项目结构与RESTful接口风格说明

    PS:再次说明一下,原本不想写的太啰嗦的,可之前那个系列发布后发现,好多朋友都想马上拿到代码立即能上手开发自己的项目,对代码结构.基础常识.分类目录与文件功能结构.常用函数......等等什么都不懂, ...

  3. 如何从MVP模式进阶到Clean模式

    从类图上来看,MVP都是一个业务一个Presenter,每个Presenter都是一个接口,它还包含了View的接口,用于定于和View相关的行为,然后Activity等业务类实现View的接口,因为 ...

  4. visio移动形状 上下左右键 移动滚动条

    今天在用visio写作业,想微移visio的形状,于是按上下左右方向键,结果移动的是滚动条. 那么如何让visio按上下左右移动的是形状,其实按Scroll键就好了.

  5. ELK系列~log4-nxlog-Fluentd-elasticsearch写json数据需要注意的几点

    经验与实践 前两篇文章里我们介绍了nxlog的日志收集和转发<ELK系列~Nxlog日志收集加转发(解决log4日志换行导致json转换失败问题)>,今天我们主要总结一下,在与log4和f ...

  6. 脱壳第二讲,手动脱壳PECompact 2.x

    脱壳第二讲,手动脱壳PECompact 2.x PS: 此博客涉及到PE格式.所以观看此博客你要熟悉PE格式 首先,逆向inc2l这个工具,汇编中可能会用的 inc头文件转换为lib的工具 但是他有壳 ...

  7. Android 自定义View实现QQ运动积分抽奖转盘

    因为偶尔关注QQ运动, 看到QQ运动的积分抽奖界面比较有意思,所以就尝试用自定义View实现了下,原本想通过开发者选项查看下界面的一些信息,后来发现积分抽奖界面是在WebView中展示的,应该是在H5 ...

  8. 四、MVC简介

    一.高内聚.低耦合 大学的时候,上过一门叫<软件工程>的课程,课程中讲到了耦合,解耦等相关的词汇,当时很懵懂,不解其意. 耦合:是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影 ...

  9. 理解typename的两个含义

    理解typename的两个含义 问题:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同? template<class T> ...

  10. Connect the Cities(prim)用prim都可能超时,交了20几发卡时过的

    Connect the Cities Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...