首先,我们要了解一下值传递和引用传递的概念!!
在了解值传递和引用传递之前,我们应该了解一下基本类型和引用类型
基本类型:是在java虚拟机上的栈空间分配出来一个空间,其中栈空间线程隔离,即不共享
引用类型:在堆(heap)中创建对象,在栈空间中创建一个引用指向堆空间的对象,其中堆空间共享。
如图所示:
num是基本类型,值就保存在变量中,而str是引用类型,变量中保存的只是实际对象的地址。一般称这种变量为"引用",引用指向实际对象,实际对象中保存着内容。
再来看一下,值传递和引用传递的区别;
值传递:意味着当将一个参数传递给一个函数时,接受的参数是一个副本,是形参对实参的值得拷贝,即两个相同的引用指向堆空间的对象;
引用传递:意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,即只有一个引用指向堆空间的对象;
注意:不要把引用传递和引用类型搞混了,引用类型不是引用传递,之间没有任何联系,两个是单独的概念;还有,java中只有值传递没有引用传递,不管是基本类型还是引用类型;
下边我们来看看他们是怎样传递的
publicclass
ExampleTest { String
str = newString("hello"); char[]
ch = { 'a', 'b', 'c'}; publicstatic
void
main(String args[]) { ExampleTest ex
= newExampleTest (); ex.change(ex.a,ex.str,
ex.ch); System.out.print(ex.str
+ "
and "); System.out.print(ex.ch+"and"); } public static
void
change(int b ,String st, charcha[]) {
b = 10; st
= "test"; cha[0]
= 'g'; }}
从上图中可以看出,java中只有值传递,
1.首先我们来看基本类型a和b,首先当a传递给方法change时,复制a的副本给b,然后当10赋值给b的时候,覆盖原来b上边的值。
2.再来看一下数组ch,首先当ch传值给方法change时,赋值ch地址变量给chr,chr是ch地址变量的副本,然后因为地址一样,所以,指向的是同一个对象,接着,改变chr中下标为0的数值,而指向对象的地址没变,所以chr操作的是和ch的同一个对象,即对象的值都改变了。
最后,我们来看一下,str和st,由于String 被修饰符final修饰,故每次都会创建新的对象。
在这里我们解释一下String创建对象的过程:
第一种方式:
使用直接赋值的方式创建,即String str = "aaa";Java对于String的管理是通过StringPool来管理的。如果StringPool中没有“aaa”这个对象,那么就会直接在StringPool中创建“aaa”,然后将这个“aaa”的对象的地址返回来,将这个地址赋值给str。如果有“aaa”这个对象,就直接将这个“aaa”的地址返回来,赋值给str(该种情况下就不会有新的对象产生)。
第二种方式:
以产生对象的方式生成String对象,即String str = new String("aaa");该种方式创建字符串,首先也会先在StringPool中查找,如果池中有”aaa“这个对象(就不会在池中创建这个对象了),那么会直接在堆(heap)中直接创建一个”aaa“,并把堆中的这个”aaa“的地址返回来,赋值给str;如果池中没有”aaa“对象,,则首先在StringPool中创建一个”aaa“,然后再在堆(heap)中创建一个”aaa“对象,然后将堆中的”aaa‘对象的地址返回来,赋值给str。该种方式创建的str会直接指向堆中所创建的”aaa“。
3.在明白了String类型的创建方式,我们就可以来说它的值传递,首先str传值给方法change,st进行拷贝,即相同的地址指向同一对象,即str和st都指向“hello”,然后,当把“test”赋值给st的时候,它会去StringPool中去查找,如果有则将地址返回给st,这是返回的地址引用就会覆盖原来的地址,这样的话st就指向了新的对象“test”,而str还是指向“=hello”,以上就是值传递的过程!!
本文深入解析Java中的值传递机制,对比基本类型与引用类型的传递差异,并通过实例代码演示String对象的创建过程及其值传递特点。

被折叠的 条评论
为什么被折叠?



