今天翻看微信上有关Java技术的公众号时,看到了一篇关于Java中值传递的问题,文章讨论了在Java中调用函数进行传参的时候到底是值传递还是引用传递这个面试时会问到的问题。之前也接触过类似的问题,但只是知道是值传递,具体到为什么,一直不是太清楚。今天看了一下,算是明白了,写个博客记录一下。

  首先先声明一下,在Java中函数传参是值传递,不是引用传递。要弄清楚这个问题之前要先弄清楚什么是值传递,什么是引用传递。

  值传递(pass by value):是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

  引用传递(pass by reference):是指在调用函数时将实际参数的地址直接传递到函数中,这样在函数中如果对参数进行修改,将影响实际参数。

  请注意我红色标记的字,很关键。相信很多人对于是值传递还是引用传递都会有这样一种认识:在传递基本数据类型的时,是值传递,在传递引用数据类型时是引用传递。原因不过就是像下面这样的代码所表现出来的。

package com.wuqi.p1;

public class ValuePassTest {

    public static void main(String[] args) {
int a = 1;
//传递基本数据类型,因为是将a的值传递给param,所以即便在pass函数中改变了
//参数的值,a的值还是不会变。所以我们认为在传递基本数据类型的时候是值传递
pass(a);
System.out.println("a= " + a);
} private static void pass(int param) {
param = 2;
System.out.println("param= " + param);
} }

package com.wuqi.p1;

import com.wuqi.p2.User;

public class PassTest2 {

    public static void main(String[] args) {
User user = new User();
user.setName("wutianqi"); //传递对象,因为是将指向User的引用user传递给了param,
//在函数中param.setName会反应到真实的对象中去。因此我们
//认为在这种情况下是引用传递
pass(user);
System.out.println("my name is " + user.getName());
} private static void pass(User param) {
param.setName("wuqi");
System.out.println("my name is " + param.getName());
} }

包括我自己以前也是这么认为的。但是我们都没有注意到这样一个问题。请看代码

package com.wuqi.p1;

public class PassTest3 {
public static void main(String[] args) {
String name = "wutianqi"; //这里传递字符串参数,按照我们以前的观点这里应该传递的是将指向字符串的name引用
//传递给param,那么在pass函数中修改参数的值会直接影响到name引用指向的字符串
//的值,那么输出的结果依此应该是 my name is wuqi my name is wuqi
pass(name);
System.out.println("my name is " + name);
} private static void pass(String param) {
param = "wuqi";
System.out.println("my name is " + param); }
}

这段代码按照我们对象是引用传递的思想,输出的结果就应该是代码中所说的那样。但是真实输出的结果确实下面这样

哎呦!什么情况!颠覆了你的认知?当初看到这段代码我也是大吃一惊!这说明之前的认识是错的!

别慌!让我们在看一下值传递和引用传递的概念吧。这里我标红的字体起作用了。引用传递是直接传递引用,那么在函数中对参数进行修改将会影响到实际参数。按照这个理论,那么毫无疑问,通过上面的例子,引用传递对于Java函数参数传递来说是错误的。在看看值传的概念,值传递是将实际参数复制一份,对参数的改变不会影响到实际参数。注意复制这两个字!!!在上面的例子中,如果我们认为是复制了name引用,也就是复制了name引用的值,然后传递给param。param="wuqi",其实相当于param=new String("wuqi"),这时param指向了一个新的对象。而实际参数name还是指向原来的对象。这样的话输出的结果和正确的就对上了。这样也就证明了在Java中是值传递而不是引用传递。

对于对象来说传递的是引用的一个副本给参数,这一点要铭记!

Java调用函数传递参数到底是值传递还是引用传递的更多相关文章

  1. javascript学习笔记(二):定义函数、调用函数、参数、返回值、局部和全局变量

    定义函数.调用函数.参数.返回值 关键字function定义函数,格式如下: function 函数名(){ 函数体 } 调用函数.参数.返回值的规则和c语言规则类似. <!DOCTYPE ht ...

  2. js中所有函数的参数(按值和按引用)都是按值传递的,怎么理解?

    我觉着我可能对这块有点误解,所以单独开个博说下自己的理解,当然是研究后的正解了. 1,参数传递是基本类型,看个例子: function addTen(num){ num += 10; return n ...

  3. JS中函数的本质,定义、调用,以及函数的参数和返回值

    要用面向对象的方式去编程,而不要用面向过程的方式去编程 对象是各种类型的数据的集合,可以是数字.字符串.数组.函数.对象…… 对象中的内容以键值对方式进行存储 对象要赋值给一个变量 var cat={ ...

  4. c&c++函数的参数和返回值的传递终结版

    c++函数的参数和返回值的传递方式有三种:值传递.指针传递和引用传递. 在这之前先看几个例子: 一, int a=10; int b=a; b+=10; 此时b是a的一个拷贝,改变b的值,a并不会受到 ...

  5. Java千百问_05面向对象(011)_引用传递和值传递有什么差别

    点击进入_很多其它_Java千百问 1.什么是值传递 值传递,是将内存空间中某个存储单元中存放的值,传送给还有一个存储单元.(java中的存储单元并不是物理内存的地址,但具有相关性) 比如: //定义 ...

  6. Python——变量的引用和函数的参数和返回值的传递方式

    变量的引用 在python中,所有的变量都是指向地址,变量本身不保存数据,而是保存数据在内存中的地址.我们用下面的程序来理解: a = 10 print(id(a)) a = 11 print(id( ...

  7. Python中定义函数时参数有默认值的小陷阱

    在定义函数的时候,如果函数的参数有默认值,有两种类型的参数,一种是整数,字符串这种不可变类型,另一种是列表这种可变类型,对于第一种情况没有什么特殊的地方,但是对于可变类型,有一个微妙的小陷阱. 可变类 ...

  8. Java调用.Net WebService参数为空解决办法 (远程)调试webservice方法 转

    Java调用.Net WebService参数为空解决办法 (远程)调试webservice方法   同事遇到一个很囧的问题,java调,netwebservice的时候,调用无参数方法成功,调用有参 ...

  9. java 一个函数EnumMap返回多个值

    java 一个函数如何返回多个值   在开发过程中,经常会有这种情况,就是一个函数需要返回多个值,这是一个问题!! 网上这个问题的解决方法: 1.使用map返回值:这个方法问题是,你并不知道如何返回值 ...

随机推荐

  1. 在 Spark 中使用 IPython Notebook

    本文是从 IPython Notebook 转化而来,效果没有本来那么好. 主要为体验 IPython Notebook.至于题目,改成<在 IPython Notebook 中使用 Spark ...

  2. poi读取excel转对象,格式转换帮助类

    //格式转换//value:原数据,parmtype:方法参数类型,cellType 单元格类型public static Object formatd(String value, String pa ...

  3. EFCore

    Nuget引用 LinqKit.Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.SqlServer 然后新建类继承DbConte ...

  4. 这可能是最详细的 iOS 学习入门指南(含书目/文档/学习资料)

    1 零基础小白如何进行 iOS 系统学习 首先,学习目标要明确: 其次,有了目标,要培养兴趣,经常给自己一些正面的反馈,比如对自己的进步进行鼓励,在前期小步快走: 再次,学技术最重要的一点就是多动手. ...

  5. linux下使用FreeRDP 连接 Windows 远程桌面

    linux下使用FreeRDP 连接 Windows 远程桌面   简介 FreeRDP 是一款开源的远程桌面系统,支持多种平台, 在 ubuntu 中使用 FreeRDP 可以很方便的登录到 win ...

  6. Linux 磁盘管理,Linux vi/vim

    一.Linux 磁盘管理 Linux磁盘管理好坏直接关系到整个系统的性能问题. Linux磁盘管理常用三个命令为df.du和fdisk. df:列出文件系统的整体磁盘使用量 du:检查磁盘空间使用量 ...

  7. vue踩坑之旅 -- computed watch

    vue踩坑之旅 -- computed watch 经常在使用vue初始化组件时,会报一些莫名其妙的错误,或者,数据明明有数据,确还是拿不到,这是多么痛苦而又令人忍不住抓耳挠腮,捶胸顿足啊 技术点 v ...

  8. Java复习3.变量.常量.String.

    Java 中的变量常量数据类型 20131004 前言: 还是国庆节,无聊的很,就没事复习点Java的知识,其实C/C++基本上是现在大型企业面试的语言,但是多学习点Java是没有坏处的,而且,将来工 ...

  9. C# 打开TXT文件读取内容

    控制关键字,有些关键字发短信发不出来,比如(金融)需要转化为(金.融) 要求:读取敏感字的,并且替换掉 using : using System.Collections.Generic;using S ...

  10. Qt出现QObject::connect: Cannot queue arguments of type '******'的解决方法

    一般出现这种情况都是自定义的类型进行型号槽连接的时候出现的,使用 假设自定义的类型是MyClass 使用qRegisterMetaType<MyClass>("MyClass&q ...