【java】数组的定义和使用

数组的基本概念

数组创建

复制代码
   T[] 数组名 = new T[N];

T:数组中存放元素的数据类型

T \[\] :代表数组本身的类型

N:数组的长度(数组能存放多少个元素)
2.

复制代码
           int[] arr1=new int[10];
           double[] array2=new double[10];
           String[] array3=new String[20];

数组两种初始化方式

  1. 动态初始化

    创建数组时,只指定数组长度,不写元素值,元素自动赋默认值

    只规定数组大小,里面元素是对应类型的默认值

    复制代码
            //静态初始化
            int[]  array1=new int[10];
  2. 静态初始化

    创建数组时,直接写出数组里面的元素,编译器自动根据大括号里元素个数算出数组长度

    复制代码
            //动态初始化
            int[]  array2=new int[]{1,2,3,4,5,6,7,8,9};
            double[] array3=new double[]{1.0,2.0,3.0,4.0};
            String[]  array4=new String[]{"tom","Lily","java"};
  3. 数组元素默认值
    当数组只开辟空间,没有手动赋值时,元素自带默认值:
    引用类型(String、类对象等)默认值:null

    复制代码
    String[] words = new String[3]; // 三个元素默认都是null


    重点注意事项

  4. 静态初始化不用手动写长度,编译器自动数{}里元素个数。

  5. {}里的数据类型必须和数组定义的类型一致。

  6. 简写格式{...}不能拆分成两行定义


复制代码
        int[] array5;
        array5=new int[]{1,3,5,3,6,7};  //这样是可行的

        int[] array6;
        array6={1,2,34,54,65};//编译报错,简写只能在定义数组那一行初始化
        
        int[] array7={1,2,3,4,5,6};  //在定数组这一行初始化,是可行的

数组的基本使用

数组中元素访问
  1. 数组在内存是连续空间,下标从 0 开始递增,通过数组下标访问元素
复制代码
           int[] array1=new int[]{10,20,30,40,50};
           System.out.println(array1[0]);
           System.out.println(array1[2]);
           System.out.println(array1[3]);
           // 修噶下标为0 的元素、
           array1[0]=1;
           System.out.println(array1[0]);
  1. 注意事项
    连续内存 → 支持随机访问,直接用下标快速读取任意位置元素。
    下标范围:[0, 数组长度),不能越界。
    数组有N个元素,下标最大是N-1
    下标越界抛出异常
遍历数组
遍历:把数组里所有元素全部访问一遍
  1. 方式 1: for 循环(能拿到数组下标)
    利用 数组名.length 获取数组长度

    复制代码
            int[] array1=new int[]{1,2,3,4,5,6};
            for(int i=0;i<array1.length;i++)
            {
                System.out.printf("%d ",array1[i]);
            }
            System.out.println();
  2. 方式 2:for-each 增强 for 循环(只读取元素,拿不到下标)
    语法: for(元素类型 变量 : 数组名)
    特点: 不用写循环条件,简化遍历
    无法获取当前元素下标

    复制代码
            //for-each 增强for循环
            int[] array2=new int[]{1,3,4,5,6};
            for(int x:array2)
            {
                System.out.printf("%d ",x);
            }
            System.out.println();

数组是引用类型

基本类型变量与引用类型变量的区别

  1. 基本类型变量 :栈里面直接存值本身

    引用类型变量:栈里面存对象在堆中的地址,对象本体放在堆里


  2. 3. 基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值
    引用数据类型创建的变量,⼀般称为对象的引用,其空间中存储的是对象所在空间的地址
    4. 引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始
    地址, 通过该地址,引用变量便可以去操作对象

  3. Java 的引用类似 C 语言指针,但 Java 不能手动对地址做加减运算,安全性更高

复制代码
   public static void func1()
   {
       int[] array1=new int[3];
       array1[0]=10;
       array1[1]=20;
       array1[2]=30;

       int[] array2=new int[]{1,2,3,4,5};
       array2[0]=100;
       array2[1]=200;

       // 变量里存的不是变量本身,而是在堆内存的地址
       array1=array2;  //两个变量共用同一块内存地址

       array1[2]=300;
       array1[3]=400;
       array1[4]=500;

       for(int i=0;i<array2.length;i++)
       {
           System.out.println(array2[i]);
       }
   }
  1. 关键总结
    Java 数组属于引用类型:
    a)变量里存的不是数组本身,而是数组在堆内存的地址;
    b)array1 = array2 只是拷贝地址,两个变量共用同一个数组对象;
    c)无论用哪个引用修改数组内部元素,都会互相影响

NULL

  1. 什么是 null
    a)null 在 Java 中表示空引用 ,是一个不指向任何对象的引用
    b)Java 里引用类型(数组、类、String 等)的变量,可以赋值为 null,代表这个引用 变量没有指向堆里的任何对象
    c)基本数据类型(int / double / boolean)不能赋值为 null,只有引用类型可以

  2. 和 C 语言 NULL 的区别
    相似点 :都代表无效的内存位置,不能读写
    重要区别 :Java 的 null 不等价于内存 0 号地址,只是 Java 层面的 "空标记",和 C 语言空指针底层含义不一样

  3. 空指针什么时候会出现
    只要用一个值为null的引用,去调用属性 / 方法 / 访问数组元素,就会触发 NPE

  4. 总结

    复制代码
            int[] arr1=null;
            int[] arr2=new int[]{1,2,3,4,5,6,7};
            System.out.println(arr1[0]);
    //        System.out.println(arr2[0]);

    a)arr1:只是一个空引用,不存在数组,arr10 空指针
    b)arr2:数组对象存在,可以访问元素,arr20 是 1


数组的应用场景

保存数据

  1. 知识点
    a)数组:用来批量保存多个同类型数据
    b)数组下标从 0 开始,最大下标 = 数组长度 -1
    c)数组名.length:获取数组元素个数
    d)for 循环:适合知道循环次数的遍历场景
复制代码
           int[] array={1,2,3};
           for(int i=0;i<array.length;i++)
           {
               System.out.println(array[i]+" ");
           }

参数传递(值传递)

Java 中只有值传递,没有引用传递

基本类型和引用类型,本质都是拷贝一份 "值" 传给方法

基本数据类型作为参数
复制代码
   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);
   }


2. 斐波那契数列

复制代码
       //方法:返回int[]数组,存放婓波那些前n项
       public static int[]fib(int n)
       {
           if(n<=0)
           {
               return null;
           }

           int[] array=new int[n];
           array[0]=array[1]=1;
           //当前项等于前两项之和
           for(int i=2;i<n;i++)
           {
               array[i]=array[i-1]+array[i-2];
           }
           return array;
       }


Arrays 工具类 和 数组知识点

Java 数组常用操作,包含Arrays工具类、数组拷贝、查找、排序、逆序

数组转字符串 Arrays.toString()

  1. 作用:快速把数组转为字符串格式打印,不用自己循环拼接
复制代码
           int[] arr=new int[]{1,2,3,4,5,6,7};
           String newArr= Arrays.toString(arr);
           System.out.println(newArr);
  1. 注意:直接打印数组对象名,输出的是地址哈希值,不是数组内容

数组拷贝

  1. 直接赋值(浅引用,不是拷贝)

    复制代码
            int[] arr=new int[]{1,2,3,4,5};
            int[] newArr=arr;  //newArr 和 arr 指向的是同一块数组
            newArr[0]=100;
            System.out.println(Arrays.toString(arr));  // newArr 的修改 会导致 arr 也被修改
  2. Arrays.copyOf / Arrays.copyOfRange(真正拷贝,生成新数组)

    复制代码
            //Arrays.copyOf/Arrays.copyOfRange 是拷贝
            int[] arr=new int[]{1,2,3,4,5,6,7};
    
            //copyOf(原数组,新数组长度)
            int[] newArr=Arrays.copyOf(arr,arr.length);
            arr[0]=10;
            System.out.println("arr: "+Arrays.toString(arr));
            System.out.println("newArr: "+Arrays.toString(newArr));  //不受arr 的影响
    
            //copyOfRange (原数组,起始下标,结束下标)  //左闭,右开
            int[] newArr2=Arrays.copyOfRange(arr,1,5);
            System.out.println("newArr2: "+Arrays.toString(newArr2));
  3. 区分
    基本类型数组拷贝没问题;
    引用类型数组拷贝是浅拷贝

  4. 自己手写数组拷贝

    复制代码
        public static int[] copyOf(int[] arr)
        {
            int[] ret=new int[arr.length];
            for(int i=0;i<arr.length;i++)
            {
                ret[i]=arr[i];
            }
            return ret;
        }

    功能:

    手写版数组拷贝,深拷贝(对于 int 基本类型数组),复制完成后,修改原数组arr不会影响新数组ret,修改ret也不会影响arr

顺序查找(线性查找)

  1. 从头到尾逐个比对元素,找到返回下标,找不到返回 -1

复制代码
       //顺序查找,找到返回下标,找不到返回-1
       public static int find(int[] arr,int data)
       {
           for(int i=0;i<arr.length;i++)
           {
               if(arr[i]==data)
               {
                   return i;
               }
           }
           return -1;
       }
  1. 缺点:
    数据量大的时候效率低
    不需要数组有序

二分查找(折半查找)

  1. 思路:取中间元素,比较目标值,缩小查找区间

复制代码
       //二分查找
       public static int  binarySearch(int[] arr,int toFind)
       {
           int left=0;
           int right=arr.length-1;
           while(left<=right)
           {
               int mid=(left+right+1)/2;
               if(toFind<arr[mid])
               {
                   right=mid-1;
               }
               else if (toFind>arr[mid])
               {
                   left=mid+1;
               }
               else
               {
                   return mid;// 找到
               }
           }

           return -1; //没找到返回 -1
       }
  1. 优点:数据越多,效率优势越大

  2. Java 自带Arrays.binarySearch()方法

    复制代码
            int ret2=Arrays.binarySearch(arr,6);
            System.out.println(ret2);

数组排序:冒泡排序

  1. 升序思路:相邻两个元素比较,前大后小就交换;

    每一轮把最大元素 "冒泡" 到末尾

  2. 降序思路:相邻两个元素比较,前小后大就交换;
    每一轮把最小元素 "冒泡" 到末尾

复制代码
       public static void bubbleSort(int[] arr)
       {
           //外层控制轮数
           //内层比较,每轮末尾 i 个已经排好的不用比较
           for(int i=0;i<arr.length;i++)
           {
               for(int j=0;j<arr.length-i-1;j++)
               {
                   //如果前面的比后面的数据大,就交换
                   if(arr[j]>arr[j+1])  //要改成降序的话,把大于改成小于就行
                   {
                       int temp=arr[j];
                       arr[j]=arr[j+1];
                       arr[j+1]=temp;
                   }
               }
           }
       }
  1. Java 内置:Arrays.sort(arr),底层是优化后的排序,性能远高于手写冒泡

数组逆序

  1. 思路:双指针,left 指向头部,right 指向尾部,交换两个元素,left++,right--,直到 left >= right

复制代码
       // 数组逆序 双指针  先交换元素,在变化指针
       public static void reverse(int[] arr)
       {
           int left=0;
           int right=arr.length-1;
           while(left<right)
           {
               int tmp=arr[left];
               arr[left]=arr[right];
               arr[right]=tmp;
            left++;
            right--;
           }
       }


二维数组

普通二维数组

  1. 二维数组本质:是一维数组,数组里每一个元素又是一个一维数组

  2. 语法格式

    复制代码
    数据类型[][] 数组名称 = new 数据类型 [行数][列数] {初始化数据};

    特点:行不能省略,列可以省略

复制代码
       // 二维数组
       public static void main(String[] args) {

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

a.length:二维数组行数

arow.length:第row行一维数组的长度(当前行的列数)

不规则二维数组

  1. 定义时只确定行数,每一行的列数不固定,各行长度不一样
复制代码
   int[][] array = new int[2][]; // 定义2行,列暂时不指定
   array[0] = new int[3]; // 第0行,3个元素(3列)
   array[1] = new int[5]; // 第1行,5个元素(5列)
  1. 第 0 行:3 列
    第 1 行:5 列
    内存理解:外层数组保存两个一维数组的地址,两个一维数组长度不同
相关推荐
麻辣布丁1 小时前
java集合篇面试模拟
java·开发语言·面试
niucloud-admin1 小时前
JAVA V6 多商户商城 开发文档——插件开发规范
java·开发语言
嘟哩DuliDuli1 小时前
创作 Agent 的任务状态该如何保存
android·java·javascript
wdfk_prog1 小时前
lely-canopen-rtt:为什么推荐在 RT-Thread 上使用 Lely CANopen 构建主站
java·运维·缓存·docker·容器
Token掘金室1 小时前
JSON模式结构化输出报错
java·服务器·json
秋饼1 小时前
Spring AI 2.0 接入 DeepSeek V4.1 Flash 生产级实战
java·ai·技术分享·后端开发
IT枫斗者枫哥1 小时前
Java 分批导出仍然 OOM?用 32 MiB 堆复现三种 CSV 写法
java
shehuiyuelaiyuehao2 小时前
算法43,外观数列,模拟算法+双指针
java·算法
lhldsg2 小时前
多商户团购系统源码:技术架构选型与二次开发实战指南
java·小程序·架构