Java中的数组

面向对象编程系列四


前言

提示:Java中数组的定义与使用


一、Java中数组

数组的定义及使用规范:

数组中存储的是相同数据类型的一块空间,且逻辑上物理上连续,下标index从零开始逐个++

数组的三种定义方式

通过new关键字来实例化对象
第一种方式【】中不加数字,但后面必须要写明数组中存储了哪些数据
或者直接省略new int【】
如果声明【】中分配的空间大小也可
注意:如果为给出数组中中数据那么默认是零
int[] array1 = new int[]{1,2,3,4,5};
int[] array2 = {1,2,3,4,5};
int[] array3 = new int[10];
//double[] array4 = new double[5];定义其他类型数组
//String[] array5 = new String[3];浮点型数组 字符串数组

遍历数组的两种方式

下面展示一些 内联代码片

array.ength可以获取一个数组的长度
注意for each循环  (数组中每个元素的类型    变量名  :数组名)
for (int i = 0; i < array1.length; i++) {
            System.out.println(array1[i]);
        }
for (int x :array1) {
            System.out.print(x);
        }

12345Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 6
如果输出的数组下标不合法则会跑出数组下标越界异常

Arrays类中的两种方法

下面展示一些 内联代码片

输出结果
[1, 2, 4, 7, 8]
Array.sort表示对数组数字从小到大排序
Arrays.toString表示将数组中数据以字符串形式输出 如图所示 有很多重载方法
根据需求进行选择
int[] array2 = {1,2,7,4,8};
Arrays.sort(array2);
System.out.println(Arrays.toString(array2));

在这里插入图片描述
数组是一个引用类型

二、JVM 堆 和 栈

在这里插入图片描述
下面展示一些 内联代码片

输出结果
[I@1b6d3586
此处输出的就是array的地址
int[] array = new int[]{1,2,3,4,5};
System.out.println(array);

在这里插入图片描述
总结:1.局部变量是定义在方法内部的变量叫做局部变量
2.局部变量的内存就是在栈上,实例化的对象在堆上
3.数组是一个引用变量,因此上图的array是一个引用类型变量
array这个引用指向对象
4.引用变量其实就是用来其所指向对象的地址的在这里插入图片描述
此时变量array4和a都是局部变量 局部变量在使用的时候必须进行初始化
下面展示一些 内联代码片

输出结果:
[I@1b6d3586
null
输出结果为null
此时array4这个引用不指向任何对象

        int[] array = new int[]{1,2,3,4,5};
        System.out.println(array);
        int[] array1 = null;
        System.out.println(array1);

在这里插入图片描述在这里插入图片描述
当一个引用为空时 引用.xxxxjvm就会抛出一个空指针异常
下面展示一些 内联代码片

输出结果:
[1, 99, 3, 4, 5]
[1, 100, 3, 4, 5]
int[] array1 = new int[]{1,2,3,4,5};
int[] array2 = new int[3];
array2 = array1;
array1[1] = 99;
System.out.println(Arrays.toString(array1));
array2[1] = 100;
System.out.println(Arrays.toString(array1));

在这里插入图片描述
总结:1.两个引用可以指向同一个对象
2.但是一个引用只可以指向一个对象
3.array2 = array1这个操作就是把array1的地址赋值给了array2 ,此时array2存储的是0x123地址 简而言之就是array2指向了array1这个引用所指向的对象
4.当两个引用指向同一个对象时,一个引用改变数组中的值时,另一个引用去访问时得到数据也是发生改变的
5.0x45这个对象没有人引用时,会被系统自动回收。

数组中形参实参的改变

在这里插入图片描述
输出结果:
[1, 2, 3]
[99, 2, 3]
总结:1.每new一次对象就在堆上开辟了一块新的内存空间
2.当数组作为形参进行传递的时候 此时传递到形参的只是一个地址
此时存在两种情况
形参指向改变array = new int【】{}
此时形参指向了在堆上新开辟的一片内存空间的对象 此时再做任何改变都不会影响实参的数值
通过形参改变实参的数组里面的值
array【0】 = 99
此时在main方法里面调用toString方法输出实参的值就会发生改变。

两种方式对数组进行扩容在堆和栈上的理解

在这里插入图片描述
下面展示一些 内联代码片

输出结果:
[1, 2, 3, 4, 5]
[2, 4, 6, 8, 10]
[4, 8, 12, 16, 20]
public static void main(String[] args) {
         int[] array = {1,2,3,4,5};
        System.out.println(Arrays.toString(array));
         int[] ret = grow1(array);
         int[] ret2 = grow2(array);
        System.out.println(Arrays.toString(ret));
        System.out.println(Arrays.toString(ret2));
    }


    public static int[] grow1(int[] array1){
        for (int i = 0; i < array1.length; i++) {
            array1[i] = array1[i] * 2;
        }
        return array1;
    }


    public static int[] grow2(int[] array2){
        int[] tmparray = new int[array2.length];
        for (int i = 0; i < tmparray.length; i++) {
            tmparray[i] = array2[i] * 2;
        }
        return tmparray;

分析:1.首先定义了一个数组array其地址为0x42 然后调用toString方法即可输出结果{1,2,3,4,5}
2.调用grow1方法将实参地址0x42传给了形参array1 array1也指向了这个数组 即两个引用指向了同一个对象 此时对数组内每个元素进行2倍扩大 return之后array1被系统回收 在main方法中用类型int【】 ret接收 所以ret收到了array1赋给它的值0x42
此时调用toString方法打印ret即可得到{2,4,6,8,10}
3.调用grow2方法实参将地址0x42传给array2 又在栈上定义了一个tmparray 并在堆上开辟了一块新的内存空间 假设其地址现在为0x78tmparray指向了这个新的数组对象并对这个新的数组对象以原数组形式扩大二倍放入新的数组中 并用ret2接收 tmparray被系统回收 此时ret2指向了这个新的数组对象
此时调用toString方法时即可输出{4,8,12,16,20}

区分深浅拷贝

在这里插入图片描述

输出结果:
[1, 1, 1, 1, 1]
Arrays.fil方法可以把数组中的元素全部替换为某一个值
public static  void main(String[] args) {
        int[] array =new int[]{1,2,3,4,5};
        Arrays.fill(array,1);
        System.out.println(Arrays.toString(array));
        }

浅拷贝:浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。

输出结果:
[1, 2, 3, 4, 5]
[99, 2, 3, 4, 5]
[99, 2, 3, 4, 5]
当array2指向的数组0下标位置发生改变时调用toString方法输出的array1和array2的结果都发生了改变

int[] array1 = new int[]{1,2,3,4,5};
int[] array2 = array1;
System.out.println(Arrays.toString(array1));
array2[0] = 99;
System.out.println(Arrays.toString(array1));
System.out.println(Arrays.toString(array2));

深拷贝:深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象
下面展示一些 内联代码片

Array.copyOf拷贝
输出结果:
[99, 2, 3, 4, 5]
[99, 2, 3, 4, 400]
[99, 2, 3]
改变array3的值array1不受影响
此时进行的是深拷贝 拷贝后的对象与原来的对象是完全隔离的
另外学习一种Arrays.copyOf方法,可以把一个数组选择指定长
度给一个新的数组,此时数组进行的也是深拷贝
例如array4
int[] array1 = new int[]{1,2,3,4,5};
int[] array3 = Arrays.copyOf(array1,array1.length);
array3[4] = 400;
System.out.println(Arrays.toString(array1));
System.out.println(Arrays.toString(array3));
int[] array4 = Arrays.copyOf(array1,3);
System.out.println(Arrays.toString(array4));

Arrays.copyOf方法的源码
在这里插入图片描述
在这里插入图片描述
下面展示一些 内联代码片

输出结果:
[0, 1, 2, 3, 4, 5, 0, 0, 0, 0]
public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] array1 =new int[10];
        System.arraycopy(array,0,array1,1,5);
        System.out.println(Arrays.toString(array1));
        }
clone深拷贝

下面展示一些 内联代码片

输出结果:
[1, 2, 3, 4, 5]
[100, 2, 3, 4, 5]}
int[] array = {1,2,3,4,5};
int[] array1 = array.clone();
array1[0] = 100;
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array1));
        }

总结:

1.在做题时数组方法有很多例如以字符串形式输出Arrays.toString 将Arrays.fill将数组中元素全部换为某一个值Arrays.sort()对数组元素进行从小到大排序Arrays.copyOf深拷贝数组
2.栈上放的一定是局部变量,引用不一定在栈上,在不在栈和是不是引用是没有关系的!!
3.注意理解二维数组其实是一种特殊的一维数组
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值