java的值传递


内容选自尚硅谷

值传递过程中的常见问题

方法中的变量叫做局部变量,局部变量都存在在栈中,对于基本数据类型,栈中存的是局部变量的值,而非地址,对于引用数据类型,栈中存的是地址,属性变量放在堆中。java中,引用类型的变量只有两种值,要么是null,要么是地址值。

在实参向形参赋值的时候,如果实参是基本数据类型,那么形参从实参接收到的数据就是基本数据类型的值
如果实参是引用数据类型,那么形参从实参接收到的数据就是指向堆空间的地址值。

在编程实现交换两个变量的值的时候

package come.atguigu.java;

public class ValueTransferTest1 {
	public static void main(String[] args) {
		int m = 10;
		int n = 20;
		System.out.println("m = "+ m + ",n = " + n);
		ValueTransferTest1 test = new ValueTransferTest1();
		test.swap(m, n);
		System.out.println("m = "+ m + ",n = " + n);
	}
	
	public void swap(int m,int n){
		int temp  = m;
		m = n;
		n = temp;
	}
}

运行结果为

m = 10,n = 20
m = 10,n = 20

以上用法是有问题的,因为形参的m,n确实是继承了实参的值,且形参的变量在栈空间中进行了数据交换过后,马上就被清空(出栈)了,没有把交换后的结果返回。
在这里插入图片描述
上图选自尚硅谷

正确的用法

想要实现两个变量的值呼唤,采用基本数据类型的变量行不通,采用引用数据类型的变量,将要交换的变量定义为类的属性,代码如下

package come.atguigu.java;

public class ValueTransferTest2 {
	public static void main(String[] args) {
		Data data = new Data();
		data.m = 10;
		data.n = 20;
		System.out.println("m = "+data.m+",n = " + data.n);
		ValueTransferTest2 test = new ValueTransferTest2();
		test.swap(data);
		System.out.println("m = "+data.m+",n = " + data.n);
	}
	
	public void swap(Data data){
		
		int temp = data.m;
		data.m = data.n;
		data.n = temp;
	}
}

class Data{
	
	int m;
	int n;
}

运行结果正确

m = 10,n = 20
m = 20,n = 10

在这里插入图片描述
实参向形参赋值的时候,在栈空间又创建了一个data变量指向堆空间的对象,在swap方法中,又创建了一个临时的局部变量temp,当方法执行完毕后,上面那个data变量和temp变量出栈,底部的data变量仍然指向堆空间的对象,对象有指向它的变量,不会被当作垃圾而回收。

ps:当实参向形参赋值的时候,会在栈空间中建立形参的变量
方法执行完毕后,会把方法内的局部变量和对象出栈,一旦堆空间对象没有栈空间的变量所指向,堆空间的对象会被当作垃圾而回收掉。

若想要对数组进行冒泡排序

public void sort(int[] arr){
		
		for (int i = 0; i < arr.length - 1; i++) {

			for (int j = 0; j < arr.length - 1 - i; j++) {

				if (arr[j] > arr[j + 1]) {
//					int temp = arr[j];
//					arr[j] = arr[j + 1];
//					arr[j + 1] = temp;
					//错误的:
//					swap(arr[j],arr[j + 1]);
					//正确的:
					swap(arr,j,j + 1);
				}

			}

		}
	}
	
	public void swap(int[] arr,int i,int j){
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

ps:在main方法中使用swap方法时,首先要创建包含swap方法的对象,因为main方法有static的修饰符,如果调用swap的方法不包含static的修饰符,可以不用创建对象,直接调用。如上面的代码所示,sort方法没有加static的修饰符,在调用swap方法时,不用创建swap方法的对象。

字符串的值传递机制

代码如下

package com.atguigu.java;

public class ValueTransferTest {
	public static void main(String[] args) {
		String s1 = "hello";  //栈空间新建一个s1的变量,指向字符串常量池的地址
		ValueTransferTest test = new ValueTransferTest();
		test.change(s1);
		System.out.println(s1);
	}
	
	public void change(String s){
		s="hi~~";
	}
}

结果为

hello

String为引用 数据类型
在这里插入图片描述
String为引用数据类型中的类,既然是类,就必须new一个对象出来,字符串String类型比较特殊,既可以像基本数据类型一样直接赋值,也可以用new的方式给字符串赋值。

String类型的字符串的值存储在字符串常量池当中,用一个char[]型的数组存放,s1存放的是数组首地址值,在java1.8中字符串常量池一般认为在堆空间,而非在方法区当中。

String s1 = "hello";

栈空间新建一个s1的变量,指向字符串常量池的地址.

	public void change(String s){
		s="hi~~";
	}

先在栈空间新建一个s的变量,依然指向’hello’字符串,再在字符串常量池中新建了一个’hi~~’的对象,把该字符串的首地址值赋给s,因此s1仍然指向hello。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值