作者:Yiyuery 链接:https://juejin.cn/post/6872202037426618382 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
局部变量/方法参数
对于局部变量和方法传递的参数在jvm中的存储方式是相同的,都是存储在栈上开辟的空间中。方法参数空间在进入方法时开辟,方法退出时进行回收。以32为JVM为例,boolean、byte、short、char、int、float以及对应的引用类型都是分配4字节大小的空间,long、double分配8字节大小空间。对于每一个方法来说,最多占用空间大小是固定的,在编译时就已经确定了。当在方法中声明一个int变量i=0或Object变量obj=null时,此时仅仅在栈上分配空间,不影响到堆空间。当new Object()时,将会在堆中开辟一段内存空间并初始化Object对象。
数组类型引用和对象
当声明数组时,int[] arr=new int[2];数组也是对象,arr实际上是引用,栈上占用4个字节大小的存储空间,而是会在堆中开辟相应大小空间进行存储,然后arr变量指向它。当声明一个二维数组时,如:int[][] arr2=new int[2][4],arr2同样在栈中占用4个字节,在堆内存中开辟长度为2,类型为int[]的数组对象,然后arr2指向这个数组。这个数组内部有两个引用类型(大小为4个字节),分别指向两个长度为4类型为int的数组。内存分布如图:
所以当传递一个数组给一个方法时,数组的元素在方法内部是可以被修改的,但是无法让数组引用指向新的数组。其实,还可以声明:int [][] arr3=new int[3][],内存分布如下:
String类型数据
对于String类型,其对象内部需要维护三个成员变量,char[] chars,int startIndex, int length。chars是存储字符串数据的真正位置,在某些情况下是可以共用的,实际上String类型是不可变类型。例如:String str=new String("hello"),内存分布如下: