【JavaSE】Java入门三(数组详解三千字)

目录

数组的定义与使用

1.什么是数组

2.数组的遍历

3.数组在JVM中的内存分布

4.Arrays工具类的使用(包含深浅拷贝问题)

 5.二维数组


数组的定义与使用

为了方便大量同种类型数据的存储和输出,Java中引入了数组的概念。

1.什么是数组

数组:可以看成相同类型元素的一个集合,在内存中一段连续的空间

数组的创建形式如下:

T[] 数组名 = new T[N];//T表示数组中存放的数组类型,N表示数组的长度

T[] 数组名称 = {data1, data2, data3, ..., datan};

数组在创建时有两种选择,我们成为动态初始化和静态初始化。

动态初始化:创建数组时,直接指定数组中元素的个数。

int[] array1=new int[10];
double[] array2 =new double[5];
String[] array3 = new String[3];

静态初始化:在创建数组时不直接指定数据元素的个数,而直接用具体的数据内容进行指定。

nt[] array1 = new int[]{0,1,2,3,4,5,6,7,8,9};
double[] array2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0};
String[] array3 = new String[]{"hell", "Java", "!!!"}

tips:

1.静态初始化时可以省去等号右边的new T[]。

2.Java中也可以按C语言形式创建数组,但是不推荐。(例如:int arr[] ={1,2,3})

静态和动态初始化均可以分成两步完成:

int[] array1;
array1 = new int[10];
int[] array2;
array2 = new int[]{10,20,30];

第一步为声明变量,第二步的作用是初始化变量

如果数组变量在声明之后未初始化是不能被使用的,否则在编译阶段会报错。

动态初始化时数组会给每个元素赋初始值。

  • 如果数组中存储类型为基本类型, 赋值如下:
  • 如果是引用数据类型,默认值为null。 

2.数组的遍历

数组在内存中是一段连续的空间,空间的编号都是从 0 开始的,依次递增,该编号称为数组的下标,我们可以通过 下标访问数组任意位置的元素
比如:
int [] array = new int []{ 10 , 20 , 30 , 40 , 50 };
System . out . println ( array [ 0 ]);
// 也可以通过 [] 对数组中的元素进行修改
array [ 0 ] = 100 ;
System . out . println ( array [ 0 ]);

在数组中可以通过.length来获取数组的长度

我们可以用循环(三种循环都可以)的方式遍历数组:

int[]array = new int[]{10, 20, 30, 40, 50};
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}

也可以通过Java中的特殊语法for-each来遍历数组:

int[] array = {1, 2, 3};
for (int x : array) {
System.out.println(x);
}

3.数组在JVM中的内存分布

首先我们需要了解JVM中的内存分布:

蓝色方框中是线程隔离的数据区(线程的概念会在后续文章中介绍到)

红色方框中是由所有线程共享的数据区。

引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该
地址,引用变量便可以去操作对象

 tips:

null在Java中是一个不指向对象的引用,

int[] arr = null;
System.out.println(arr[0]);
// 执行结果
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:6)

如果一个引用变量的值为null则说明它并没有指向堆空间,此时就不能对这个变量进行任何读写操作。 

4.Arrays工具类的使用(包含深浅拷贝问题)

Java中提供了java.util.Arrays包,其中包含了一些操作数组的常用方法。

比较常用的有,数组转字符串,数组排序,数组拷贝,下面我会详细介绍这三种方法。

  1. 数组转字符串
    import java.util.Arrays
    int[] arr = {1,2,3,4,5,6};
    String newArr = Arrays.toString(arr);
    System.out.println(newArr);
    // 执行结果
    [1, 2, 3, 4, 5, 6]

    使用Arrays.toString方法可以让打印数组更加方便.

  2. 数组排序

    public static void main(String[] args) {
    int[] arr = {9, 5, 2, 7};
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));
    }

    该方法默认升序排序,是一种非常高效的排序方法,它的内部运用了多种排序算法:数组长度为n,则1 <= n < 47 使用插入排序
    数组长度为n,则47 <= n < 286 使用使用快速排序
    数组长度为n,则286 < n 使用归并排序或快速排序(有一定顺序使用归并排序,毫无顺序使用快排)

  3. 数组拷贝

    import java.util.Arrays;
    public static void func(){
    // newArr和arr引用的是同一个数组
    // 因此newArr修改空间中内容之后,arr也可以看到修改的结果
    int[] arr = {1,2,3,4,5,6};
    int[] newArr = arr;
    newArr[0] = 10;
    System.out.println("newArr: " + Arrays.toString(arr));
    // 使用Arrays中copyOf方法完成数组的拷贝:
    // copyOf方法在进行数组拷贝时,创建了一个新的数组
    // arr和newArr引用的不是同一个数组
    arr[0] = 1;
    newArr = Arrays.copyOf(arr, arr.length);
    System.out.println("newArr: " + Arrays.toString(newArr));
    // 因为arr修改其引用数组中内容时,对newArr没有任何影响
    arr[0] = 10;
    System.out.println("arr: " + Arrays.toString(arr));
    System.out.println("newArr: " + Arrays.toString(newArr));
    // 拷贝某个范围.
    int[] newArr2 = Arrays.copyOfRange(arr, 2, 4);
    System.out.println("newArr2: " + Arrays.toString(newArr2));
    }

    这里需要注意,如果数组中是基本数据类型在拷贝时没有问题,如果是引用数据类型,需要考虑深浅拷贝问题

什么是深浅拷贝呢?

我们在上面数组的内存分布中以及知道,在栈中数组变量名内储存的只是堆空间的开始地址。

浅拷贝:即只将堆空间的地址名拷贝了一份存到了新变量中,两个变量指向同一块地址。

深拷贝:将堆空间中的地址重新拷贝了一份,并且栈中新变量名内存的是新空间的开始地址。

浅拷贝:

深拷贝:

 5.二维数组

二维数组的本质也是一维数组,不过每个元素又是一个一维数组。

基本语法:数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };

int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr[row].length; col++) {
System.out.printf("%d\t", arr[row][col]);
}
System.out.println("");
}

需要注意二维数组在动态初始化时,行数是必须确定的,列数不做规定。

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值