首页投稿(暂停使用,暂停投稿)Java学习笔记

Java值传递与引用传递深度解析

2016-08-01  本文已影响257人  何知晓

众所周知,Java存在8种基础数据类型。
不过,Java字节码中还有额外的两种基础数据类型,分别是reference type与returnAddress type。

想要学习Java 中的参数传递,就必须理解JVM是如何解释基础数据类型与引用数据类型的。

一切皆数据?一切皆对象?

我们先从最基础的赋值开始:

Object A = new Object();

new Object() 做了什么?

JVM将在GC堆中开辟一定大小的空间用以存放此Object,此Object是引用数据类型(注意不是reference类型)。

Object A 做了什么?

JVM将在虚拟机栈中此线程栈开辟出一个slot用以存放A,注意此处A为reference type。(slot可以理解为用以存放基础数据类型的线程私有的空间)

“ = ” 做了什么?

reference type 的A被赋值为先前new Object() 指令所产生的引用数据类型的一个对象。

案例分析

static String s1 = "abc" ;

public static void changeString(String s2){

s2="bcd";

}

changeString(s1);

运行以上代码,s1改变了吗?

答案是没有。

为什么呢?

因为JVM中传递的不是reference本身,而是reference的拷贝。

或者你可以理解为传递的是一个int类型的数据,不过这个int类型比较特殊,里面存放有一个对象的地址。

我们来一步一步分析上面的代码:

String s1 = "abc";
//JVM开辟了一定大小的空间用以存放一个String对象,我们假设这个空间的起始值为0x8000。那么reference类型的s1就被赋值为0x8000。

void changeString(String s2){
//JVM中传递的是基础数据类型reference ,此时开辟一个线程帧,为s2开辟一个slot,其值与s1相同,为0x8000

s2="bcd"; 
// 我们假设“bcd”的地址为0x9000,那么s2作为一个reference类型的数据将被赋值为0x9000

}

所以,函数changeString() 所做的只是新建了一个reference类型的数据s2,然后把“bcd”的地址赋值给了s2,对于s1和s1所指向的对象“abc”没有做任何事,我们当然也看不到任何改变了。

综上所述,JVM中传递的所有数据都是基础数据类型的数据,只是JVM会解析这是一个普通的数据类型还是 reference type 或 returnAddress type 。

所以,所有对形如s2这样的传入reference进行 = 的赋值,都不会改变s1的数据,即s1依然会指向原来的对象。

用不太严谨的话来说:Java中传递引用数据类型本质是传递其地址的拷贝。

所以,才说Java中只有值传递。

不过,值传递与引用传递并不能完全区分来看,将引用数据类型看做是传递引用对于理解Java、日常编程并无不可。

上一篇下一篇

猜你喜欢

热点阅读