博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 值传递_Java只有值传递
阅读量:6454 次
发布时间:2019-06-23

本文共 2332 字,大约阅读时间需要 7 分钟。

可能有很多小伙伴都知道Java是值传递,但是又说不出个所以然,我也是这样,于是去看了一些博客,下面来一个简单的总结。

首先说结论:Java中只有值传递,没有引用传递。

这里涉及到值传递和引用传递两种传递机制:

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

引用传递(pass by reference):在调用方法(函数)时,将实参的地址直接传递到函数中,那么在函数中对形参进行修改,将影响到实参。

下面来看看上面定义的重点:

值传递

引用传递

根本区别

复制实参

不复制实参

修改的是什么?

形参

实参改变否?

不改变

改变

实参和形参的概念我想不必再提了,大家应该都懂。

可能看到这里有的小伙伴会说:基本数据类型是值传递,引用数据类型是引用传递。

以前我也是这么认为,但是实际上是错误的。我们再看看我们修改的是什么?

形参啊!你传递了一个对象进去,结果修改的是对象的属性,对象的属性是你传的形参吗?即使你把对象的所有属性都改了,那也不是形参啊!!!!

为了方便理解,我们先看下图:

a1918ca1db142a1ee595956987c3bd51.png

基本数据类型在栈中保存的就是变量,但是引用数据类型在栈中保存的是地址,凭什么你传给形参的时候传栈里面的值,但是你修改的时候要修改堆里面的内容?

所以我们应该修改的形参也应该是栈中的数据。

下面我们直接来看代码验证我的结论:

public classDemo04 {public static voidmain(String[] args) {int a = 2;

System.out.println(a);//结果为2//值传递

change(a);

System.out.println(a);//结果为2

}public static void change(inta){

a= 10;

}

}

对于这里的结果大家应该没有异议。接下来看这段代码:

public classDemo05 {public static voidmain(String[] args) {

String str= "学渣很忙";//String可是引用数据类型哟

System.out.println(str);//学渣很忙

change(str);

System.out.println(str);//学渣很忙

}public static voidchange(String str){

str= "张三";//上面这句话等价于下面这句话,忽略入不入字符串常量池//str = new String("张三");

}

}

为什么对于引用数据类型String来说,前后的结果并没有改变呢?看了change方法的注释你大概就懂了,修改形参的值就是new

了一块新的内存空间,也就是说我们修改的是将栈中原来保存的地址值复制了一份给形参,然后形参中修改了这个地址值。内存图如下

4e259530ad6c29296338fe5c8351a752.png

需要明确的一点是,我们在被调方法(函数)中操作的是形参,而复制的一份形参也是压入栈中,所以修改形参应该是修改栈中的值。

然后就是修改形参的值,对于基本数据类型就可以直接在栈中修改;对于引用数据类型需要通过保存在栈中的地址值找到堆中的数据。但是这并不影响我们修改形参,如果此时你修改的不是形参而是堆中的属性,那当然会对属性产生影响。但是我们要修改形参,也就是new 一个新的内存空间,把new出来的地址值赋值给形参,这才是真正的修改形参。

最后是结果比较,如果你真的是修改的形参,你在内存图中看看原来的实参有没有变化呢?答案是实参没有改变。

我的结论得到了验证:Java中只有值传递,没有引用传递。小伙伴们可以试一下对0x1234进行修改,然后画画内存图作为练习;下面是我给出的答案:

public classDemo06 {public static voidmain(String[] args) {

Student student= newStudent();

student.name= "张三";

student.age= 21;

System.out.println("修改形参前的student:"+student);

change(student);

System.out.println("修改形参后的student:"+student);

changeAttribute(student);

System.out.println("修改属性后的student:"+student);

}//这里才是修改的形参

public static voidchange(Student student){

student= newStudent();

student.name= "王麻子";

student.age= 35;

System.out.println("change方法中的student:"+student);

}//这样修改是修改的属性,而不是参数

public static voidchangeAttribute(Student student){

student.name= "李四";

student.age= 12;

}

}classStudent{

String name;intage;

@Overridepublic String toString() {//用来输出对象的名字和年龄的

return "name=" + name + ", age=" +age;

}

}

这是运行结果:

5f55c9f76e877057bc3fe0ce8fda1c55.png

9923a3d1422adf2c571d846621afed0d.png

内容到这儿就结束啦,初学小白,如有错误烦请各位大佬及时指出!感谢!

转载地址:http://rdyzo.baihongyu.com/

你可能感兴趣的文章
批处理文件
查看>>
1.每次按一下pushbutton控件,切换图片?
查看>>
Python 嵌套列表解析
查看>>
[GXOI/GZOI2019]旧词——树链剖分+线段树
查看>>
android 补间动画的实现
查看>>
2017年广东省ACM省赛(GDCPC-2017)总结
查看>>
第十届蓝桥杯B组C++题目详解和题型总结
查看>>
树的存储结构2 - 数据结构和算法42
查看>>
简单理解函数回调——同步回调与异步回调
查看>>
Android 多个Activity 跳转及传参
查看>>
anroid 广播
查看>>
AJAX POST&跨域 解决方案 - CORS
查看>>
关于最小生成树中的kruskal算法中判断两个点是否在同一个连通分量的方法总结...
查看>>
【译】Linux系统和性能监控(4)
查看>>
开篇,博客的申请理由
查看>>
点滴积累【C#】---C#实现上传word以流形式保存到数据库和读取数据库中的word文件。...
查看>>
Ubuntu常用笔记
查看>>
Token和session 详解
查看>>
JMeter IP欺骗压测
查看>>
Serializers 序列化组件
查看>>