Java中的数组使用方法
1、定义数组:Type[] arrayName; 该数组只能存储Type类型及其子类的数据
public static void main(String[] args){
int[] arrayInt; //int类型的数组,其只能存储int类型的数据
double[] arrayDouble; //double类型的数组,其只能存储double类型的数据
Object[] arrayObject; //Object类型的数组,其能存储Objecte类型的数据,也可以存储Objecte类的子类数据
}
- 对于基本的数据类型,如int与double,不存在子类继承的问题,因此此时数组只能存放该基本了类型的数据
- 但Object类是一种大类,例如String类继承了Object类,因此arrayObject可以存在String类型的数据
2、数据初始化:为数组分配内存空间、为每个数组元素赋值
- 静态初始化:显示指定数据元素的值(指定值,不指定长度,系统自动分配长度)
- 动态初始化:显示指定数组的内存空间(指定长度,不指定元素的值,系统自动为元素分配值)
//静态初始化
public static void main(String[] args){
int[] arrayInt;
arrayInt=new int[] {1,2,3,4};
double[] arrayDouble;
arrayDouble=new double[]{1.2,3.4};
Object[] arrayObject;
arrayObject=new String[]{"hello"}; //因为String类继承了Object类
}
上述静态初始化可以简写成:
//静态初始化简写
public static void main(String[] args){
int[] arrayInt=new int[] {1,2,3,4};
double[] arrayDouble=new double[]{1.2,3.4};
Object[] arrayObject=new String[]{"hello"};
}
//动态初始化
public static void main(String[] args){
int[] arrayInt;
arrayInt=new int[4];
double[] arrayDouble;
arrayDouble=new double[2];
Object[] arrayObject;
arrayObject=new String[1];
}
上述动态初始化可以简写成:
//动态初始化简写
public static void main(String[] args){
int[] arrayInt=new int[4];
double[] arrayDouble=new double[2];
Object[] arrayObject=new String[1];
}
3、访问数组元素:
方法一:使用arrayName.length来确定数组的长度,然后使用for循环来逐个访问数组内的元素
public static void main(String[] args){
int[] arrayInt=new int[] {1,2,3,4};
for(int i=0;i<arrayInt.length;i++){
System.out.println(arrayInt[i]);
}
}
方法二:使用foreach语句,不需要知道数组的长度
public static void main(String[] args){
int[] arrayInt=new int[] {1,2,3,4};;
for(int i:arrayInt){ //i会以此访问arrayInt数组中的每一个元素
System.out.println(i); //输出i即可
}
}
foreach语句会依次将数组元素赋值给变量i(该语句也可使用与集合中,来遍历集合的每一个元素)
方法三:使用Arrays类中的toString静态方法(详细见后面第7部分),但是注意,该方法只是用来输出这个数组的所有元素而已,不能像前两个办法那样,来访问单独的一个数组元素。
toString将数组转换成一个字符串,每个数组元素之间采用英文逗号隔开
import java.util.Arrays;
public class t {
public static void main(String[] args){
int[] a=new int[] {1,2,3,4};
System.out.println("a数组的元素是:"+Arrays.toString(b)); //输出b数组
}
}
输出结果:a数组的元素是:[1, 2, 3, 4]
4、数组底层的运行机制
创建并初始化数组时,其实包括了两个部分:一个是数组的引用变量、一个是数组本身
如:int[] a=new int[] {1,2,3,4}; 其包括引用变量arrayInt(存放于栈内存中)、数组本身[1,2,3,4](存放于堆内存中)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TkV3D4AY-1589427331549)(C:\Users\24973\AppData\Roaming\Typora\typora-user-images\image-20200511112242960.png)]
public static void main(String[] args){
int[] a;
a=new int[4]; //动态初始化,此时系统自动分配数值,int型赋值为0
//为数组赋值
for(int i=0;i<a.length;i++) {
a[i]=i+1;
}
}
其整个在内存中的运行机制如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JovjjehL-1589427331550)(C:\Users\24973\AppData\Roaming\Typora\typora-user-images\image-20200511112838530.png)]
5、引用类型的数组:此时的数组类型Type不在是基本数据类型,而是引用类型
class Person{
int age; //年龄
int height; //身高
public void info() {
System.out.println("年龄是:"+age+"身高是:"+height);
}
}
public class Test {
public static void main(String[] args) {
//定义并动态初始化一个Person[]数组,名字是students,其内包含两个Person变量
Person[] students=new Person[2];
Person zhang=new Person();//创建一个Person对象,并将这个对象赋给zhang这个变量
Person le=new Person();//创建一个Person对象,并将这个对象赋给le这个变量
}
}
上述过程的内存示意图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEQ7vnnM-1589427331552)(C:\Users\24973\AppData\Roaming\Typora\typora-user-images\image-20200512091032618.png)]
(1)动态初始化数组,系统默认赋值为null
(2)创建两个Person变量,由于Person类中定义了两个int型的age、height变量,因此初始化是系统默认赋值0
//Person类
class Person{
int age; //年龄
int height; //身高
public void info(String name) {
System.out.println(name+"的年龄是:"+age+",身高是:"+height);
}
}
public class Test {
public static void main(String[] args) {
//阶段一
//定义并动态初始化一个Person[]数组,名字是students,其内包含两个Person变量
Person[] students=new Person[2];
Person zhang=new Person();//创建一个Person对象,并将这个对象赋给zhang这个变量
Person le=new Person();//创建一个Person对象,并将这个对象赋给le这个变量
//阶段二
//为zhang和le赋值
zhang.age=24;
zhang.height=160;
le.age=25;
le.height=180;
//阶段三
students[0]=zhang;//将zhang变量的值赋给第一个数组元素
students[1]=le; //将le变量的值赋给第二个数组元素
//输出
zhang.info("zhang");
students[0].info("zhang");
}
}
整个过程的内存示意图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h078q4CY-1589427331555)(C:\Users\24973\AppData\Roaming\Typora\typora-user-images\image-20200512092610266.png)]
输出结果:zhang的年龄是:24,身高是:160
zhang的年龄是:24,身高是:160
(1)将zhang和le赋给数组后,数组中的两个元素都变成了引用变量,并且与zhang、le指向的是同一个内存区
(2)输出时,zhang与students[0]的输出结果相同,因为两者指向的内存区域相同
6、多维数组:其实是指定了一个一维数组,然后这个一维数组的每一个元素又指向一个数组
public static void main(String[] args){
int[][] array; //定义一个二维数组
array=new int[2][]; //将array当成一个一维数组,进行动态初始化
//遍历数组中的每一个元素
for(int i=0;i<array.length;i++) {
System.out.println(array[i]);
}
//初始化数组的第一个元素
array[0]=new int[3]; //第一个数组元素指向了一个类型为int、长度为3的数组
//遍历数组中的每一个元素
for(int i=0;i<array[0].length;i++) {
System.out.println(array[0][i]);
}
//初始化数组的第二个元素
array[1]=new int[2]; //第二个数组元素指向了一个类型为int、长度为2的数组
array[1][0]=4; //显示指定array数组中第二个元素所指数组的第一个元素
//遍历数组中的每一个元素
for(int i=0;i<array[1].length;i++) {
System.out.println(array[1][i]);
}
}
内存中的运行机制如图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xt8kCNek-1589427331557)(C:\Users\24973\AppData\Roaming\Typora\typora-user-images\image-20200512110907175.png)]****
输出结果:null
null
0
0
0
4
0
(1)定义了array数组后,其包含两个元素,而这两个元素都是数组即引用类型,因此动态初始化后,系统默认赋值为null,此时这两个元素都没有任何指向
(2)初始化array中的两个元素后,第一个元素指向一个长度为3的int型数组,第二个元素指向一个长度为2的int型数组,从这里可以看出,Java中的二维数组,它的每一列长度可以不同
(3)初始化array后的两个元素后,每个元素都指向一个基本类型的数组,不在是引用类型,因此系统默认初始化为0
(4)然后程序显式指定array数组第二个元素所指向的数组的第一个元素为4,即进行了数组赋值
注意:在上面的例子中,当给array数组的第一、第二个元素初始化时,只能将其指向int型的数组,因为一开始就定义了array数组时int型的
a[0]=new String[3] ; //定义错误,因为类型不匹配
从上面可以看出,Java中的多维数组,其实都可以当成是一维数组来处理,只不过其每一个数组元素又再次指向一个新的数组,而这个新的数组的每一个元素,又指向另外一个更新的数组,以此类推,得到了Java中的多维数组
7、Java中的Arrays类:需导入 java.util.Arrays
对于其中由static定义的静态方法,直接采用Arrays.方法名调用即可(查询JAVA的API文档)
import java.util.Arrays;
public class t {
public static void main(String[] args){
int[] a=new int[] {6,2,9,4};
int[] b=Arrays.copyOf(a,a.length); //赋值a数组,生成一个新的b数组
System.out.println("b数组的元素是:"+Arrays.toString(b)); //输出b数组
Arrays.sort(a);//对a数组进行排序————升序排序
System.out.println("排序后的a数组的元素是:"+Arrays.toString(a));
}
}
提醒:查询API文档时,所有static修饰的方法都可以直接采用类名.方法名来调用,如果是void修饰,则不需要用新的变量来接收返回值,直接使用即可,例如void sort(type[] a)方法,直接采用Arrays.sort(a);。如果不是void方法修饰的,如type[] copyOf(type[] a,int length),需要采用新的一个数组来接收方法的返回值。