Java中的数组

Java中数组相关知识总结

有些地方和c中还是有区别的

一.数组基本用法

1.什么是数组

 在Java中,数组也就是相同类型元素的集合,它可以让我们“批量”创建相同类型的变量。数组的内存是连续的。

2.创建数组

 基本语法:

int[] array1={1,2,3,4,5};
int[] array2=new int[]{1,2,3,4,5};
int[] array3=new int[5]   //没有进行初始化

 在上述三种创建方法中要注意区分后两种的区别
 后两者都有一个new,new会在堆内存里为数组分配一块空间来存储数据,此时的变量名是放在栈中的,变量名中存放的是堆中数组的首地址,称此变量名为引用
 第一种虽然没有new,但效果和new了一个对象是一样的

示意图如下:在这里插入图片描述

3.数组的使用

①获取长度&访问元素问题

代码示例:

int[] arr={1,2,3};

//获取数组长度
System.out.println("length="+ arr.length);   //结果为3

//访问数组中的元素
System.out.println(arr[1])      //结果 2
System.out.println(arr[2])      //结果 3
arr[2]=100;
System.out.println(arr[2])      //结果 100

②数组下标越界问题
代码示例:

int[] arr={1,2,3};
System.out.println(arr[100]);

//执行结果
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:100
          at Test.main(Test.java:4)

抛出了异常,所以要注意数组下标越界问题

注意
  ·–使用 数组名.length 能够获取到数组的长度,. 这个操作为成员访问操作符,length不是方法,是一个属性
  ·–使用[ ] 按下标取数据元素,要注意下标是从0开始计数的
  ·–使用[ ] 操作既能读取数据,也可以修改数据
  ·–下标访问操作不能超出有效范围[0,length-1],超出范围,会显示数组越界异常(运行期间)
  ·-- 当定义好的数组没有被初始化,如果是简单类型初始值为0,如果是引用类型,初始值为NULL


③数组遍历问题
代码示例1:

//使用for循环来遍历数组
public class Test {
    public static void main(String[] args) {
       int[] arr={1,2,3,4,5};
        for (int i = 0; i <arr.length ; i++) {
            System.out.println(arr[i]);
        }
    }
}

代码示例2:

//使用for-each来遍历数组
 int[] arr={1,2,3,4,5};
        for (int x:arr) {
            System.out.println(x);
        }

foreach用法:
for(表达式1(数组当中的变量值):表达式2(数组名)){ }

for和for-each的区别?
 for循环是通过数组的下标访问数组元素。foreach不能够用下标去访问,它定义的变量是直接存放数组中的值的,foreach能够更方便的完成对数组的遍历,可以避免循环条件和更新语句的错误。


二.数组作为方法的参数

1.基本用法

 我们将数组的遍历以方法的形式来写
代码如下:

public class Test {
    public static void printArray(int[] arr1) {  //arr1为形参
        for (int x : arr1) {
            System.out.println(x);
        }
    }


    public static void main(String[] args) {
        int[] arr = {1, 2, 3};    //arr为实参
        printArray(arr);
    }
}

 在Java中传参数有按址传递和按引用传递(也算按值传递)按引用传递是将一个引用中的地址值给了另一个引用,两个引用所指空间是一样的。

如图所示:在这里插入图片描述

2.理解引用类型(不作深究)

①参数传内置类型
代码示例:

public class Test {
    public static void main(String[] args) {
        int num = 0;
        func(num);
        System.out.println("num=" + num);
    }

    public static void func(int x){
        x=10;
        System.out.println("x="+x);
    }
}

//执行结果
x=10
num=0

我们发现形参的改变不影响实参num的值


②参数传数组类型
代码示例:

public class Test {
    public static void main(String[] args) {
        int[] arr={1,2,3};
        func(arr);
        System.out.println("arr[0]="+arr[0]);
    }

    public static void func(int[] arr1){
        arr1[0]=10;
        System.out.println("arr1[0]"+arr1[0]);
    }
}

// 打印结果
arr1[0]=10;
arr[0]=10;

 认真比较上述两个代码,一个第一个传递的是值,第二个传递的是引用。

两者区别如图:
在这里插入图片描述

  

什么是引用呢?
  引用相当于一个“别名”,也可以理解为一个指针
创建一个引用也就是相当于在栈上创建了一个很小的变量,这个变量保存了一个整数,这个整数表示内存中的一个地址,由上述图可以看到,当new一个数组是,堆就分配一块空间给数组,之后用int[]来接受,相当于创建了一个int[]变量,这个变量名就是引用类型,里面保存了堆里数组的起始地址


注意

① System.out.println(array);
//打印出来是数组地址经过哈希的一个值,并不是十六进制的地址

②int[] array=NULL;
System.out.println(array.length);   //这里length是一个属性
//会出现空指针异常

③String str=“asdfg”;
System.out.println(str.length());  // 这里length是一个方法
//打印结果为5

 在点号之前若为NULL,运行时都会出现空指针异常


3.简单了解JVM内存区域划分(重要)


在这里插入图片描述
 ①程序计数器:只是一个很小的空间,保存下一条执行的指令地址
 ②虚拟机栈:重点是存储局部变量表也可以是其他信息
 ③本地方法栈:与虚拟机栈作用类似,只不过保存的内容是Native方法的局部变量,在有些版本中,本地栈和虚拟机栈是连在一起的
 ④堆:JVM所管理的最大的内存区,使用new创建的对象都在堆上保存
 ⑤方法区:用于存储已经被虚拟机加载的类信息,静态变量,字节码文件信息等数据
 ⑥运行时常量池:方法区的一部分

Native方法
  JVM是一个基于c++实现的程序,在Java程序执行过程中,本质上也需要调用c++提供的一些函数进行和操作系统底层进行一些交互
这里的Native方法就是指这些c++实现的,再由Java来调用的函数

想要了解更多JVM内存的,可以自己去深究一下


三.数组作为方法的返回值

代码示例(写一个方法,将数组中每个数都*2)

//直接修改原数组
public class Test {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3};
        transform(arr);
        printArray(arr);
    }

    public static void transform(int[] arr){
        for (int i = 0; i <arr.length ; i++) {
            arr[i]=arr[i]*2;
        }
    }
    
       public static void printArray(int[] arr) {
        for (int x : arr) {
            System.out.println(x);
        }
    }
}

  上述代码破坏了原有的数组,试试在方法内部创建一个新的数组,并由方法返回回来。


代码如下

//返回一个新的数组再打印出来
public class Test {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3};
         int[] show=transform(arr);
        printArray(show);
    }

    public static int[]  transform(int[] arr){
        int[] ret=new int[arr.length];
        for (int i = 0; i <arr.length ; i++) {
            ret[i]=arr[i]*2;
        }
        return ret;
    }
    public static void printArray(int[] arr) {
        for (int x : arr
                ) {
            System.out.println(x);
        }
    }
}

 由于数组是引用类型,返回的时候只是将这个数组的首地址返回给函数调用者,没有拷贝数组的内容,更加高效

四.数组其他知识

1.将数组以字符串形式输出
  在这里有个Arrays,是Java当中操作数组的一个工具类,所以在使用前要导入包

import java.util.Arrays;

int[] arr={1,2,3,4,5,6};

String newArr=Arrays.toString(arr);
System.out.println(newArr);

//打印结果
[123456]

2.数组拷贝方法
 ①System.arraycopy(参数表); 底层是native方法,运行速度快
 ②Arrays.copyOf(参数表); 这种内部调用了①的方法,所以时间慢
 ③array.clone(参数表);
 ④for循环进行拷贝

深拷贝和浅拷贝
 对于数组当中是简单类型来讲,就是深拷贝
 对于数组当中是引用类型来讲,就是浅拷贝
如果两个引用同时指向一个对象,那么通过修改当前对象的值后,另一个引用所指的值也会进行修改,这种就是浅拷贝
示意图理解:在这里插入图片描述
 我们可以看到深拷贝是直接将值拷贝到另一个新的数组中,改变新数组中的值,旧数组中的值并不会因此改变
 如果是引用类型,拷贝的是地址,新旧指的是同一个对象,所以改变新的数组,旧的数组里面的值也就发生了改变,这样就是浅拷贝


五.二维数组

 二维数组本质上也就是一维数组,只不过每个元素又是一个一维数组

1.二维数组的定义

//规则二维数组的定义
int[][] array1={{1,2}{3,4}{5,6}};
int[][] array2=new int[][]{{1,2}{3,4}{5,6}};
int[][] array3=new int[3][4];

//不规则二维数组定义
int[][] array4={{1}{3,4}{5,6}};
int[][] array5=new int[][4]; //行可以省略,列不可以

2.二维数组示意图
在这里插入图片描述
3.打印二维数组

public class Test {
    public static void main(String[] args) {
        int[][] arr = {{1, 2}, {2, 3}, {3, 4}};
        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("");
    }
}



//还有一种打印方法
System.out.println(Arrays.deepToString(arr));

当然还有三维数组,四维数组等,只不过出现频率都很低

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值