概念
java提供的数组是用来存储固定大小,相同类型的元素的。
基本使用方法
public class ArrayTest {
/**
* 一维数组的使用
*/
@Test
public void array1test() {
// 数组的定义,java在定义数组时并不为数组元素分配内存,因此[]中无需指明数组长度
int intArray1[];
int[] intArray2;
// 如果要为数组分配空间,需要用到new操作符
intArray1 = new int[5];
// 数组的初始化
// 1.静态初始化,即声明数组的同时进行初始化
int intArray3[] = {1,2,3,4};
// 2.动态初始化,先声明数组,之后再进行初始化
int intArray4[] = new int[5];
intArray4[0] = 1;
intArray4[1] = 2;
intArray4[2] = 3;
intArray4[3] = 4;
intArray4[4] = 5;
// 数组的引用,采用数组名加下标的方法,下标从0开始,每个数组都有一个length属性来表明数组的长度
System.out.println("intArray4[0]: " + intArray4[0]);
System.out.println("length of intArray4:" + intArray4.length);
// 数组的遍历
// 1. for循环
for(int i=0; i<intArray4.length; i++)
System.out.println("intArray4[" + i + "]:" + intArray4[i]);
// 2. 增强的for循环,也称为foreach循环
for(int var : intArray4)
System.out.println(" " + var);
}
/**
* 二维数组的使用
*/
@Test
public void array2Test(){
/**
* 二维数组,可以看做是数组的数组,空间是不连续的,所以不要求二维数组每一维大小相同
*/
// 数组的声明
int intArray5[][] = {{1,2},{2,3},{1,3}};
int intArray6[][] = new int[2][3];
int intArray7[][] = {{1,2},{1,2,3},{1,2,3,4}};
int intArray8[][] = new int[3][];
intArray8[0] = new int[2];
intArray8[1] = new int[3];
}
数组的内存分配
一维数组的内存分配情况
public class ArrayTest {
/**
* java数组必须经过初始化才能使用,而数组一旦初始化该数组所占的内存空间,数组长度都是不可变的。
*/
/**
* 一维数组的内存分配情况
*/
@Test
public void array3Test(){
// 静态初始化,初始化元素的个数决定了数组大小
int array0[] = {1,2,3,4,5};
System.out.println("array0地址: " + array0);
for(int i=0; i<array0.length; i++){
System.out.println("array0[" + i + "]: " + array0[i]);
}
// 动态初始化,需要给出数组的大小
int array1[] = new int[6];
System.out.println("array1地址: " + array1);
for(int i=0; i<array0.length; i++){
System.out.println("array1[" + i + "]: " + array1[i]);
}
array0 = array1;
System.out.println("现在array0的地址是: " + array0);
}
}
运行结果:
array0地址: [I@e285c6
array0[0]: 1
array0[1]: 2
array0[2]: 3
array0[3]: 4
array0[4]: 5
array1地址: [I@1be5d1
array1[0]: 0
array1[1]: 0
array1[2]: 0
array1[3]: 0
array1[4]: 0
现在array0的地址是: [I@1be5d1
-
从程序中运行中可以看出,采用静态初始化数组array0时,首先在栈内存中分配一个指向堆内存的地址,然后再堆中分配一段连续的内存空间,保存初始化数据,由此可见,采用静态初始化时,不用指定数组大小,程序会根据初始化数组自动识别数组大小。
-
采用动态初始化时,需要先指定数组大小,程序自动将堆中的数组初始化为默认数值,int类型,自动初始化为0.
Java内存对象访问定位0.png -
当运行程序array0 = array1时,就是将array0指定array1指向堆内存中的地址,此时array0和array1指向了同样的地址,array0之前指向的地址变成了垃圾。
Java内存对象访问定位1.jpg
二维数组的内存分配情况
package jdk.collection;
import org.junit.Test;
public class ArrayTest {
/**
* 二维数组的内存分配情况
*/
@Test
public void array4Test(){
// 不指定二维
int array2[][] = new int[3][];
System.out.println("array2地址:" + array2);
for(int i=0; i<array2.length; i++)
System.out.println("array2[" + i + "]:" + array2[i]);
// 指定二维
int array3[][] = new int[3][2];
System.out.println("array3地址: " + array3);
for(int i=0; i<array3.length; i++)
System.out.println("array3[" + i + "]:" + array3[i]);
System.out.println("array3[2][1] = " + array3[2][1]);
array3[1] = array3[0];
array3[2] = new int[3];
for(int i=0; i<array3.length; i++)
System.out.println("array3[" + i + "]:" + array3[i]);
}
运行结果:
array2地址:[[I@e285c6
array2[0]:null
array2[1]:null
array2[2]:null
array3地址: [[I@1be5d1
array3[0]:[I@13fd745
array3[1]:[I@1327b79
array3[2]:[I@12410ac
array3[2][1] = 0
array3[0]:[I@13fd745
array3[1]:[I@13fd745
array3[2]:[I@2c41f4
- 从程序运行结果可以看出,当不指定二维大小时,int array2[][] = new int[3][]创建了一个指向3个地址的地址,并且3个地址指向null;而int array3[][] = new int[3][2]创建了一个指向3个地址的地址,并且这3个地址分别指向了3个初始化为0的内存空间。
java二维数组实际上是指向地址的地址,因而array3[1] = array3[0]; array3[2] = new int[3]表明,array3[1]指向了array3[0]的地址,而array3[2]指向了一个新的含有3个int类型的地址。
Java内存对象访问定位3.png存放对象类型的数组
首先定义一个Person类
package jdk.collection;
public class Person {
private String name;
private int age;
public Person(){};
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// public String toString(){
// return "name: " + name + " age:" + age;
// }
}
定义存放Person对象的数组
package jdk.collection;
import org.junit.Test;
public class ArrayTest {
@Test
public void array5Test(){
Person array4[];
// System.out.println("array4地址:" + array4); // 编译不过去
array4 = new Person[3];
System.out.println("array4地址:" + array4);
//直接进行初始化
Person array5[] = {new Person("张三",16),new Person("李四",20)};
System.out.println("array5地址:" + array5);
for(int i=0; i<array5.length; i++){
System.out.println("array5[" + i + "]地址:" + array5[i]);
System.out.println("array5[" + i + "].getname:" + array5[i].toString());
}
// 先声明再初始化
Person array6[] = new Person[3];
for(int i=0; i<array6.length; i++){
// System.out.println("初始化前array6[" + i + "]地址:" + array6[i]);
// System.out.println("初始化前array6[" + i + "]内容:" + array6[i].toString());
}
Person per0 = new Person("王五",17);
Person per1 = new Person("周六",18);
array6[0] = per0;
array6[1] = per1;
// for(int i=0; i<array6.length; i++){
for(int i=0; i<2; i++){
System.out.println("赋值后array6[" + i + "]地址:" + array6[i]);
System.out.println("赋值后array6[" + i + "]内容:" + array6[i].toString());
}
System.out.println("per0地址:" + per0 + " per1地址:" + per1);
}
运行结果
array4地址:[Ljdk.collection.Person;@e285c6
array5地址:[Ljdk.collection.Person;@1be5d1
array5[0]地址:jdk.collection.Person@13fd745
array5[0].getname:jdk.collection.Person@13fd745
array5[1]地址:jdk.collection.Person@1327b79
array5[1].getname:jdk.collection.Person@1327b79
赋值后array6[0]地址:jdk.collection.Person@12410ac
赋值后array6[0]内容:jdk.collection.Person@12410ac
赋值后array6[1]地址:jdk.collection.Person@2c41f4
赋值后array6[1]内容:jdk.collection.Person@2c41f4
per0地址:jdk.collection.Person@12410ac per1地址:jdk.collection.Person@2c41f4
可以类比二维数组,存放对象类型的一维数组,就是定义了一个指向数组,该数组指向存放对象的地址。
Person array4[];仅仅声明了array4是一个指向Person对象的数组,并没有为其分配地址,只有在new之后才为其分配了。
Person array5[] = {new Person("张三",16),new Person("李四",20)}定义了一个指向2个Person类型数组的引用,而Person array6[] = new Person[3]仅仅定义了一个指向3个person类型数组的引用,数组并没有初始化,因而无法知道数组指向的地址。
Java内存对象访问定位5 (1).png
而对array6进行复制之后,其内存分配情况如图所示,与array5相比较,多了2个单独指向person的引用。
网友评论