在Java中,有基本数据类型和引用数据类型。
基本数据类型:整数,浮点,字符,布尔
引用数据类型:类,接口,数组,枚举,注解
基本数据类型,都存在栈中,引用数据类型会在栈中存一个名字,值存在堆中,如果要调用这个对象的话,通过这个名字(里面含有堆中的地址),可以在堆中找到对应的存储单元。
下面这个图是创建了一个数组int a[i],数组是引用数据类型,所以指向堆中一个大小分成i块的存储单元。
那么假设i为3,是不是就有i[0] i[1] i[2]三个数据。
它在内存中的地址分布却是i[0]=0x01,i[1]=0x05,i[2]=0x09。 因为int是4字节的,所以两个数之间的距离是4字节。
那也就是说数组的内存地址实际上是这样运算的:a[i] = a[0] + i * 0x04
int[] a=new int[2];
a[1]=2
System.out.println(a[1]);
a[1] 的这个 “[ ]”实际上是一个运算符,它会拆解为 a[1]=a[0] + 1 * 0x04 然后去找这个地址所对应的值是多少,再给你显示出来。
我们上面已经分析了一维数组的地址分布,以及数组寻址原理了,那二维数组是怎么寻址的呢?经过我的思考,我认为可能是这样的把。
我们改成二维数组——二维数组,就是在一维数组里,再创建一个数组。即:
就是把上面这个图拉伸一下。
上面作为例子,是a[2][2]
这个时候就是 [0][0]、[0][1]、[0][2] [1][0]、[1][1]、[1][2] ……
那么也就是说,i控制这个列表的行数,j控制这个列表的列数。
如果你要求第二行第一个的地址,你就要先把第一行的大小全部加上,然后再加一个单位大小(0x04)。
也就是说,第二行第一个元素的地址为第一行所有大小和再加上这个元素本身的大小。
那么第三行第二个元素的地址就为前两行所有元素的大小,再加上两个单位大小。
如果i>1 (我发现第二个公式在行数大于2的时候,每多一行,会少一个单位大小)
a[i][j]= i * 数组长度 * 单位大小 - 0x03 + (j+1) * 单位大小
否则
a[i][j] = a[0][0] + i * ((数组长度-1)*单位大小) + (j+1) * 单位大小
也就是说,前两行执行第二个式子,后面的都执行第一个式子。
我们带入一个a[2][0] 看看,即求第三行,第一个的地址。
a[2][0] = 2 * 3 * 0x04 -0x03 + (0+1) * 0x04 =
2 * 3 * 0x04 是算前两行所有块都为0x04. 然后因为首地址为0x01 所以要减去0x03,就得到了前两行的大小和。
然后再加上第一个值的大小。
上面分了两种情况,你可以试一下为什么。你会发现用第二种算大于2行的数组,会每组小一个单元大小。
上面是其中一种,还有第二种情况:
我们还是从一维数组开始,这是横着的了。然后在一维数组中再加一个一维数组。
你会发现与上面的区别,只是i和j换了一下。
那么公式就是:
如果j>1
a[i][j]= j * 数组长度 * 单位大小 - 0x03 + (i+1) * 单位大小
否则
a[i][j] = a[0][0] + j * ((数组长度-1)*单位大小) + (i+1) * 单位大小
欢迎查错。。。。
网友评论