Java值传递和引用传递详细解说
前天在做系统的时候被Java中参数传递问题卡了一下,回头查阅了相关的资料,对参数传递问题有了新的了解和掌握,但是有个问题感觉还是很模糊,就是 Java中到底是否只存在值传递,因为在查阅资料时,经常看到有人说Java只有值传递,但有人说既有值传递,也有引用传递,对于两个观点个人觉得应该是 站的角度不同而得出两个不同的说法,其实两个说法其中的原理是一样的,只要咱们懂得其中的原理,那么至于叫什么也就无所谓了,下面是我在网上看到的一个帖 子,解释的感觉挺全面,就转过来,以供以后学习参考:
1:按值传递是什么
指的是在方法调用时,传递的参数是按值的拷贝传递。示例如下:
- public class TempTest {
- private void test1(int a){
- //做点事情
- }
- public static void main(String[] args) {
- TempTest t = new TempTest();
- int a = 3;
- t.test1(a);//这里传递的参数a就是按值传递
- }
- }
按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。
示例如下:
- public class TempTest {
- private void test1(int a){
- a = 5;
- System.out.println("test1方法中的a="+a);
- }
- public static void main(String[] args) {
- TempTest t = new TempTest();
- int a = 3;
- t.test1(a);//传递后,test1方法对变量值的改变不影响这里的a
- System.out.println(”main方法中的a=”+a);
- }
- }
运行结果是:
- test1方法中的a=5
- main方法中的a=3
2:按引用传递是什么
指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。
示例如下:
- public class TempTest {
- private void test1(A a){
- }
- public static void main(String[] args) {
- TempTest t = new TempTest();
- A a = new A();
- t.test1(a); //这里传递的参数a就是按引用传递
- }
- }
- class A{
- public int age = 0;
- }
3:按引用传递的重要特点
传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
示例如下:
- public class TempTest {
- private void test1(A a){
- a.age = 20;
- System.out.println("test1方法中的age="+a.age);
- }
- public static void main(String[] args) {
- TempTest t = new TempTest();
- A a = new A();
- a.age = 10;
- t.test1(a);
- System.out.println(”main方法中的age=”+a.age);
- }
- }
- class A{
- public int age = 0;
- }
运行结果如下:
- test1方法中的age=20
- main方法中的age=20
4:理解按引用传递的过程——内存分配示意图
要想正确理解按引用传递的过程,就必须学会理解内存分配的过程,内存分配示意图可以辅助我们去理解这个过程。
用上面的例子来进行分析:
(1):运行开始,运行第8行,创建了一个A的实例,内存分配示意如下:


(2):运行第9行,是修改A实例里面的age的值,运行后内存分配示意如下:
(3):运行第10行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽。
内存分配示意如下:

由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图如下:
也就是说:是两个变量都指向同一个空间。
(4):运行第3行,为test1方法中的变量a指向的A实例的age进行赋值,完成后形成的新的内存示意图如下:
此时A实例的age值的变化是由test1方法引起的
(5):运行第4行,根据此时的内存示意图,输出test1方法中的age=20
(6):运行第11行,根据此时的内存示意图,输出main方法中的age=20
5:对上述例子的改变
理解了上面的例子,可能有人会问,那么能不能让按照引用传递的值,相互不影响呢?就是test1方法里面的修改不影响到main方法里面呢?
方法是在test1方法里面新new一个实例就可以了。改变成下面的例子,其中第3行为新加的:
- public class TempTest {
- private void test1(A a){
- a = new A();//新加的一行
- a.age = 20;
- System.out.println("test1方法中的age="+a.age);
- }
- public static void main(String[] args) {
- TempTest t = new TempTest();
- A a = new A();
- a.age = 10;
- t.test1(a);
- System.out.println(”main方法中的age=”+a.age);
- }
- }
- class A{
- public int age = 0;
- }
运行结果为:
- test1方法中的age=20
- main方法中的age=10
为什么这次的运行结果和前面的例子不一样呢,还是使用内存示意图来理解一下
6:再次理解按引用传递
(1):运行开始,运行第9行,创建了一个A的实例,内存分配示意如下:
(2):运行第10行,是修改A实例里面的age的值,运行后内存分配示意如下:
(3):运行第11行,是把main方法中的变量a所引用的内存空间地址,按引用传递给test1方法中的a变量。请注意:这两个a变量是完全不同的,不要被名称相同所蒙蔽。
内存分配示意如下:
由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图如下:
也就是说:是两个变量都指向同一个空间。
(4):运行第3行,为test1方法中的变量a重新生成了新的A实例的,完成后形成的新的内存示意图如下:
(5):运行第4行,为test1方法中的变量a指向的新的A实例的age进行赋值,完成后形成的新的内存示意图如下:
注意:这个时候test1方法中的变量a的age被改变,而main方法中的是没有改变的。
(6):运行第5行,根据此时的内存示意图,输出test1方法中的age=20
(7):运行第12行,根据此时的内存示意图,输出main方法中的age=10
7:说明
(1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。
(2):在Java里面只有基本类型和按照下面这种定义方式的String是按值传递(个人以为是引用传递,但是在被调用方法中改变时相当于new了一个字符串),其它的都是按引用传递。就是直接使用双引号定义字符串方式:String str = “Java私塾”
转自http://blog.csdn.net/zzp_403184692/article/details/8184751
public class TestString {
static void changePerson(Person a){
a.name="aname";
}
static void changePersonNew(Person a){
a=new Person();
a.name="newname";
}
static void changeString(String a){
a="a";
}
public static void main(String[] args) {
Person p = new Person();
p.name="123";
changePerson(p);
System.out.println(p.name);
Person p1 = new Person();
p1.name="123";
changePersonNew(p1);
System.out.println(p1.name);
String b="b";
changeString(b);
System.out.println(b);
}
}
class Person{
public String name="shz";
Person(){}
}
结果;
aname
123
b
Java值传递和引用传递详细解说的更多相关文章
- 【Java】 参数的传递:值传递与引用传递讨论
内容稍多,可直接看第4点的讨论结果 前言 在涉及到传递参数给方法时,容易出现一些参数传递错误的问题,这就涉及到了参数的传递问题,必须搞清楚:参数是如何传递到方法中的?一般来说,参数的传递可以分为两种: ...
- Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义
一.Java中什么叫做引用类型变量?引用:就是按内存地址查询 比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...
- java中值传递和引用传递
最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...
- Java中的值传递和引用传递
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
- java的值传递和引用传递
昨天博主在对于值传递和引用传递这里栽了一个大坑啊,导致一下午时间都浪费在这里,我们先说下值传递和引用传递java官方解释: 值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对 ...
- java中方法的参数传递机制(值传递还是引用传递)
看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java 编程语言只有值传递参 ...
- java 对象传递 是 值传递 还是 引用传递?
这个问题说实话我感觉没有太大的意义. 按第一印象和c++的一些思想去理解的话对象传递是引用传递,因为传递过去的对象的值能被改变. 但是又有很多人,不知道从哪里扣出来一句,java中只有值传递,没有引用 ...
- java参数传递时到底是值传递还是引用传递
java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...
- Java面向对象-方法的值传递和引用传递
Java面向对象-方法的值传递和引用传递 0 发布时间:『 2016-08-21 14:21』 博客类别:Java核心基础 阅读(197) 评论(0) Java面向对象-方法的值传递和引用传递 方 ...
- Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
随机推荐
- 数据结构C语言实现系列——线性表(线性表链接存储(单链表))
#include <stdio.h>#include <stdlib.h>#define NN 12#define MM 20typedef int elemType ;/** ...
- date_default_timezone_set()设置时区
<?php echo function_exists(date_default_timezone_set)."<br>";//在这他总是返回1,这函数是判断这里面 ...
- ASP.NET中数据邦定效率问题的一点看法 - 转载(自由的天空)
在 做Asp.NET开发的时候经常用到DataList.Repeater等,用这些控件的时候经常用到数据邦定,很多程序员都是按照MS提供的方 法<%#DataBinder.Eval(Contai ...
- 怎样创建FTP服务器
怎样创建FTP服务器 2008-05-06 08:42永远的探索|分类:操作系统/系统故障| 浏览6382次 我准备用局域网内的一台机器做FTP服务器,创建FTP服务器一定要用Windows serv ...
- LAMP平台搭建菜鸟入门级实验
LAMP平台搭建(菜鸟入门级) mysql 安装: (1)二进制安装 二进制安装 ,执行解压配置即可.无须执行三布安装. (2)源码编译安装 安装准备工作: (1)查看系统配置:#uname -a/ ...
- SilverlightERP&CRM源码(可用于开发基于Silverlight的CRM,OA,HR,进销存等)
SilverlightERP系统源代码(支持创建OA.SilverlightCRM.HR.进销存.财务等系统之用) 可用于开发以下系统 SilverlightERP SilverlightCRM Si ...
- 解决ftp连接出现 无法从控制 Socket 读取。Socket 错误 = #10054。
ftp连接会显示以下错误信息 无法从控制 Socket 读取.Socket 错误 = #10054 或者是这样的信息 Opening data channel for directory list.T ...
- webpack +vue开发(1)
首先安装 node.js这是毋庸置疑的,安装完了之后安装webpack npm install webpack -g 接下来创建一个自己的文件夹 webpack-learn在里面创建一个index.h ...
- HelloWorld
1.创建一src目录,并创建一个文本文件 2.将文件重命名为Hello.java,并用notepad打开 3.编写代码 4.将源代码编译为类文件 Java编译器(javac.exe)的作用是将Java ...
- Spark ML 文本的分类
最近一直在研究Spark的分类算法,因为我们是做日志文本分类,在官网和各大网站一直没找到相应的Demo,经过1个多月的研究,终于有点成效. val sparkConf = new SparkConf( ...