Java基础:关于值传递和引用传递

一、程序语言中的参数传值机制

程序语言中的值传递和引用传递一般是相对函数而言的,也就是语言中的方法参数,那么我们先来回顾一下有关参数传递给方法(或函数)的两个专业术语:

  • 按值调用(call by value)

  • 按引用调用(call by reference)

1.按值调用

表示方法接收的是调用着提供的值

2.引用调用

表示方法接收的是调用者提供的变量地址(如果是C语言的话来说就是指针啦,当然java并没有指针的概念)。

⭐这里我们需要注意的是:一个方法可以修改传递引用所对应的变量值而不能修改传递值调用所对应的变量值,这句话相当重要,这是按值调用与引用调用的根本区别。

值类型与引用类型的差别

  • 基本类型在内存中占据固定大小的空间,因此被保存在栈内存中
  • 从一个变量向另一个变量复制基本类型的值,复制的是值的副本
  • 引用类型的值是对象,保存在堆内存
  • 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针
  • 从一个变量向另一个变量复制引用类型的值的时候,复制是引用指针,因此两个变量最终都指向同一个对象

二、Java中的参数传值机制

JAVA采用值调用,即call by value。

⭐方法中所有参数都是“值传递”,方法得到的是所有参数值的一个拷贝,也就是“传递的是值的副本”。 也就是说,我们得到的是“原参数的复印件,而不是原件”。因此,复印件改变不会影响原件,方法并不能修改传递给它的任何参数变量的内容。

1.基本数据类型参数的传值

⭐传递的是值的副本。 副本改变不会影响原件。

2.引用类型参数的传值

⭐传递的是值的副本。但是引用类型指的是“对象的地址”。
因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值,也意味着原参数指向对象的值也发生了改变”。

下面我们来举个基本数据类型和引用类型参数传值的栗子li’zi

public class Parameter {
	//基本数据类型
	public static void main(String[] args) {
		int a=6;    //a被初始化为6
		f(a);      
		System.out.println(a);//输出6
	}
	public static void f(int x){//局部变量x被初始化为a值的一个拷贝(也就是10)
		x=66;                     //x被改为66 x未被改变
	}                             //x被回收
}
public class Parameter {
	//引用类型
	public static void main(String[] args) {
		int[] a= {6};       //a指向自己的地址
		f(a);               
		System.out.println(a[0]);//输出66
	}
	public static void f(int[] x) //方法中的x被初始化为a的拷贝,这里指向对象地址110
	{                             //指向同一个对象 实现拷贝引用 
		x[0]=66;        //x和a同时引用的110对象内部值被修改          
	}                   //方法结束x被释放,而a依然指向a对象地址。
}

⭐虽然到这里两个数据类型的传递都分析完了,也明白的基本数据类型的传递和引用数据类型的传递区别,前者将不会修改原数据的值,而后者将会修改引用所指向对象的值。

可通过上面的实例我们可能就会觉得java同时拥有按值调用和按引用调用啊,可惜的是这样的理解是有误导性的,虽然上面引用传递表面上体现了按引用调用现象,但是java中确实只有按值调用而没有按引用调用。到这里估计不少人都?了,下面我们通过一个反例来说明(回忆一下开头我们所说明的按值调用与按引用调用的根本区别)。

public class Parameter {
	public static void main(String[] args) {
		int[] a= {6};
		int[] b= {8};
	    swap(a,b);    //交换a,b的拷贝  
		System.out.println(Arrays.toString(a));//输出[6]
		System.out.println(Arrays.toString(b));//输出[8],所以未实现交换
	}
	public static void swap(int[] x,int[] y){//x被初始化为a值的一个拷贝6 y初始化为8
		int[] temp=x;                     
		x=y;
		y=temp;                   //x=8 y=6
	}                             //x,y被回收 a,b未被改变
}

我们发现数组a和b的值并没有发生变化,也就是方法并没有改变存储在变量a和b中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝的值而已,最终,所做的事都是白费力气罢了。在方法结束后x,y将被丢弃,而原来的变量a和b仍然引用这个方法调用之前所引用的对象。

3.总结

  • 一个方法不能修改一个基本数据类型的参数(数值型和布尔型)。
  • 一个方法可以修改一个引用所指向的对象状态,但这仍然是按值调用而非引用调用。
  • 上面两种传递都进行了值拷贝的过程。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值