第四篇:Java只有值传递

一、前言

高级语言中函数的参数传递方式只有三种,传值(按值传递),传引用(按引用传递),传地址(按地址传递)。java只有值传递没有引用传递。记住,有的博客中说java引用类型是引用传递,这种说法从语法上严格来说是错误的,有引用和有引用传递是两个概念。

对于高级语言的参数传递一定要从内存模型开始,Java语言中,基本类型(8种)存放在栈内存,引用类型(3种)引用存放在栈内存,实际对象存放在堆内存,由栈内存中的引用指向堆内存中的对象,从而建立关系。

二、代码

2.1 函数参数为基本类型(值传递)

public class ParameterPassingTest {
 
	public static void _swap(int a,int b){
		//此种方法 交换两个数 不使用中间变量
		a=a+b; 
		b=a-b; 
		a=a-b; 
		System.out.println("_swap  a: "+a+",b: "+b);
	}
	public static void main(String[] args) {
       int a=1,b=2;
       _swap(a, b);
       System.out.println("main   a: "+a+",b: "+b);
	}
 
}

输出:

_swap  a: 2,b: 1
main   a: 1,b: 2

内存分析:

在这里插入图片描述

小结:可以看出_swap()方法中a,b两数发生交换,但是main()函数中a,b两数数值没有相应改变。

原因:基本类型存放在栈内存中,函数参数传递方式为值传递。

2.2 函数参数为引用类型(还是值传递)

2.2.1 引用传递??

代码1:

package mypackage;
 
public class ParameterPassingTest {
	int a;
 
	public static void _swap(ParameterPassingTest test1, ParameterPassingTest test2) {
		// 此种方法 交换两个数 不使用中间变量
		test1.a = test1.a + test2.a;
		test2.a = test1.a - test2.a;
		test1.a = test1.a - test2.a;
		System.out.println("_swap  a: " + test1.a + ",b: " + test2.a);
	}
 
	public static void main(String[] args) {
		ParameterPassingTest test1 = new ParameterPassingTest();
		test1.a = 1;
		ParameterPassingTest test2 = new ParameterPassingTest();
		test2.a = 2;
		_swap(test1, test2);
		System.out.println("main   a: " + test1.a + ",b: " + test2.a);
	}
 
}

输出1:

_swap  a: 2,b: 1
main   a: 2,b: 1

内存图:

在这里插入图片描述
在这里插入图片描述

小结:乍看之下,引用类型完成了我们所需要的数值交换功能,我们认为它是引用传递,其实不然,请读者继续往下阅读。

2.2.2 引用是另一种形式的值

代码2:

package mypackage;
 
public class ParameterPassingTest {
	int a;
 
	public static void _swap(ParameterPassingTest test1, ParameterPassingTest test2) {
		// 此种方法 交换两个数 不使用中间变量
		ParameterPassingTest temp = test1;
		test1 = test2;
		test2 = temp;
 
		System.out.println("_swap  test1.a: " + test1.a + ",test2.a: " + test2.a);
	}
 
	public static void main(String[] args) {
		ParameterPassingTest test1 = new ParameterPassingTest();
		test1.a = 1;
		ParameterPassingTest test2 = new ParameterPassingTest();
		test2.a = 2;
		_swap(test1, test2);
		System.out.println("main   test1.a: " + test1.a + ",test2.a: " + test2.a);
	}
 
}

输出2:

_swap  test1.a: 2,test2.a: 1
main   test1.a: 1,test2.a: 2

内存图:

在这里插入图片描述

在这里插入图片描述

小结: 引用类型的引用存放在栈内存中,对象存放在堆内存中,函数参数传递的是引用而不是对象,这里的引用是另一种形式的值,仍为值传递。正是因为是值传递,所有swap()函数中交换引用,主函数中并没有受到影响。

2.2.3 当引用是集合框架的引用时…

代码3:

package mypackage;
 
import java.util.ArrayList;
import java.util.List;
 
public class ParameterPassingTest {
	public static void main(String[] args) {
 
		List list = new ArrayList();
		list.add("a");
		list.add("b");
		testReferenceParam(list);
		System.out.println("main list : " + list);
	}
 
	public static void testReferenceParam(List list) {
		list.add("c");
		list = new ArrayList<>();
		list.add("d");
		System.out.println("temp list : " + list);
	}
 
}

输出3 :

temp list : [d]
main list : [a, b, c]

内存图:

在这里插入图片描述

小结:再次强调——引用类型的引用存放在栈内存中,对象存放在堆内存中,函数参数传递的是引用而不是对象,引用只是另一种形式的值,所以仍为值传递。这串代码相对于前面更加明显的说明了引用类型的值传递含义,正是因为是值传递,所以当形参list指向一块新的内存区域时,main()函数中的实参的引用所指对象没有受到影响。

三、尾声

无论是基本类型作为参数传递,还是引用作为参数传递,实际上传递的都是值,只是值的的形式不用而已。所以,Java中的参数传递方式只有值传递,完成了。

天天打码,天天进步!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祖母绿宝石

打赏一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值