Java的值传递和引用传递

写在前面:

    在Java语言中,虽然没有指针概念,但是实际上,在声明一个引用类型变量,创建对象时,在底层却是应用到了指针。这样导致了在很多相似的代码,但最终的结果,我们却不是很理解,今天为大家简单的总结一下,希望能解你的疑惑。

(1)首先我们了解一下常量池的概念

常量池:顾名思义,是指存储常量的地方,独立于堆和栈之外的一个地方-方法区。

String a="abc";
StringBuffer b= new StringBuffer("abc");

首先,我们根据这两行代码来分析一下Java常量池的作用。

第一句:String a="abc";这句话创建了几个对象?答案:最多一个对象,最少不创建。

因为在创建一个String字符串时,Jvm首先会通过equals方法,判断,常量池中,是否已经存在"abc"这个对象,如果equals方法,返回为true,那么说明常量池中已经有该字符串,则不会创建一个新的对象,而是常量池中这个对象的引用返回给变量a。

再来看第二句:StringBuffer b=new StringBuffer("abc");答案:最少一个,最多两个。

因为,对于StringBuffer类,new 一个StringBuffer,就会在堆中开辟一块内存空间,并将这块空间的引用赋给变量b。并且,如果在常量池中,如果已经有了"abc"这个字符串,Jvm就不会再创建新的对象,而是将堆中的空间,指向常量池中已经存在的"abc"这个对象。

(2)基本类型和引用类型在内存中的保存

在Java中,数据类型分为9大基本数据类型和对象类型,那么相对应的,变量也分为基本类型变量和引用类型变量。

基本类型变量:在内存中保存的是变量的值。(9大基本数据类型+String)

引用类型变量:在内存中保存的是其引用的地址的值。(StringBuffer,StringBuilder,数组等)

(3)值传递和引用传递

介绍了上面概念,现在我们大概可以理解什么是值传递和引用传递了。

值传递:在方法调用的时候,实际参数将自己的值传递给方法中的形式参数,为形式参数初始化自己的内存单元内容,但是实际上,实际参数和形式参数占据的是两个不相同的内存空间,所以改变形式参数的值,并不会影响实际参数。

引用传递:我们已经知道引用类型变量在内存中保存的是其引用的地址,所以,在传递的时候,会把他引用的地址传递给形式参数,这时,实际参数和形式参数指向的一块相同的内存空间。这样,在操作形式参数的时候,实际上也是在操作他们共同指向的空间,会改变他们那块内存空间中的值。

下面来看这个例子:

public class Test1 {

	public static void main(String[] args) {
		// 测试引用传递 在方法中,和方法调用后的不同
		
		StringBuffer str1=new StringBuffer("hello");
		StringBuffer str2=new StringBuffer("hello");
		changevalue(str1,str2);
		System.out.println(str1);
		System.out.println(str2);
		
	}

	public static void changevalue(StringBuffer str1,StringBuffer str2) {
		
		str1.append("world");
		str2=str1;
		System.out.println("在方法调用时:"+str1);
		System.out.println("在方法调用时:"+str2);
		
	}
}

那么我们再来看控制台的输出结果:

在方法调用时:helloworld
在方法调用时:helloworld
helloworld
hello
我们一步一步来分析:

A:首先,StringBuffer分别创建对象str1,str2,值都为hello,在传递参数的过程中,传的都是引用地址,分别指向str1,str2这两块空间

B:其次,在调用方法changevalue()时,str1.append,是操作了str1指向的那一块空间,改变了str1的指向空间中保存的值,所以打印str1时,打印的时helloworld。

再看,str2=str1,这时是把str1的引用地址给了str2,所以,打印str2,也是helloworld。但是这时我们要注意!!!!str2只是形式参数,我们改变了形式参数的引用地址,并没有操作这份空间!!!!

C:最后,当方法调用结束之后,str1操作的内存中,值已经改变,而str2仍然指向最开始hello那块空间,所以再次打印,str1是helloworld,而str2仍是hello。

(4)不可变类和可变类

如果上述的你还没有理解,那么再看这个点---不可变类和可变类。

不可变类:是指这个类中的对象的值一旦初始化就不可以被改变,一旦改变就创建一个新的对象,并指向新的一块内存空间。

可变类:可变类是指,在对象创建结束之后,这个对象的内容可以改变。也就是:我们在操作对象的时候,实际上是在操作这个对象的那块内存空间,改变里面的值。例如:StringBuffer,StringBuilder。


注:也有很多人说,Java中都是值传递,没有引用传递,大家不要担心,是因为他们把地址的传递也当做是一种值,这个仁者见仁,智者见智啦。要像搞清楚,得问sun公司了,哈哈。

    这样,我们就基本明白了什么是值传递,什么是引用传递,希望你在平常操作字符串的时候,不会出现错误,希望我的文章会对你有所帮助,嘿嘿。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值