java基础知识5(数组)

数组

数组概念

数组是存储同一种数据类型多个元素的集合,也可以看成是一个容器;

一维数组定义格式

数据类型[ ] 数组名 = new 数据类型[数组的长度];

一维数组初始化

  • 动态初始化:只指定长度,由系统给出默认初始化值;
    int[] arr = new int[5];
    整数类型:byte、short、int、long默认初始化值是0;
    浮点类型:float、double默认初始化值是0.0;
    布尔类型:boolean默认初始化值是false;
    字符类型:char默认初始化值是’\u0000’;
    char 在内存中占两个字节,是16个二进制位,\u0000,每个0其实代表的是16进制的0,那么四个0代表的就是16个二进制位;
    引用数据类型:初始值为null;
int[] arr = new int[5];
arr : [[email protected];//数组首地址
其中:
   [ 代表是数组,几个就是几维;
   I 代表是int类型;
   @ 是固定的;
   19bb25a代表的是16进制的地址值;
   
  • 静态初始化:给出初始化值,由系统决定长度;

java中内存分配

  • 栈 :存储局部变量
    局部变量:定义在方法声明上和方法中的变量;
  • 堆:存储new出来的数组和对象;
  • 方法区
  • 本地方法区:和系统相关
  • 寄存器:给CPU使用
    java基础知识5(数组)上图为:一个数组内存图
    java基础知识5(数组)
    上图为:三个引用两个数组图

静态初始化一维数组

  1. 格式
    数据类型[] 数组名 = new 数据类型[ ] {元素1,元素2,…};
  2. 简化格式
    数据类型[] 数组名 = {元素1,元素2,…};
  3. 静态初始化的内存分配
    int[] arr后,会在堆内存空间中开辟一片连续的地址空间,并初始化值为空间中每个元素值为0,之后再根据{11,22}进行显示赋值;
int[] arr; 
arr = new int[] {11,22};//非简化格式可以先声明再赋值

int[] arr2;
arr2 = {11,22};//报错,简化格式不可以先声明再赋值

int[] arr = new int[2]{11,22};//报错,不允许动静结合,即中括号[ ]中有值,大括号中也有值

越界和空指针

  1. ArrayIndexOutOfBoundsException:数组索引越界异常
  2. NullPointerException:空指针异常(数组已经不在指向堆内存中)

二维数组

二维数组的格式1

  1. int[ ][ ] arr = new int [3][2];(建议)
  2. 数据类型 数组名[ ][ ] = new 数据类型[m][n];
  3. 数据类型[ ] 数组名[ ] = new 数据类型[m][n];
int[] x,y[];//x是一维数组,y是二维数组;

二维数组格式1的内存图解

先在堆空间中开辟3个连续空间,初始值为null,然后为每个一维数组开辟两个连续空间,初始值为0,并把每个空间的地址值赋给开辟的3个连续空间,最后把开辟的3个连续空间的地址值返回给栈中的arr变量;java基础知识5(数组)

二维数组格式2

  • int[][] arr = new int[3][];//一维数组还未被赋值
  • arr[0] = new int[3]; //自定义一维数组大小
  • arr[1]= new int[5];
int[][] arr = new int[3][]; //三个一维数组都没有被初始化
arr[0] = new int[3]; //初始化一维数组
arr[1]= new int[5]; //初始化一维数组
System.out.println(arr[0]); //初始化过了,所以输出结果为该一维数组的地址:[[email protected]
System.out.println(arr[1]); //初始化过了,所以输出结果为该一维数组的地址:[[email protected]
System.out.println(arr[2]); //没有初始化,所以输出null

二维数组格式2的内存图解

java基础知识5(数组)

二维数组格式3

  • int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
System.out.println(arr);  //[[[email protected],二维数组地址值(两个中左括号)
System.out.println(arr[0]);  //[[email protected],一维数组地址值
System.out.println(arr[0][0]);  //1,一维数组中的元素值

二维数组格式3的内存图解

java基础知识5(数组)

java中的参数传递问题

public static void main(){
    int a = 20;
    int b = 10;
    change(a,b);//基本数据类型的值传递
    System.out.println(a+" " +b);//由于change方法改变的是它内部的变量的值,所以主方法中的a和b变量值没有改
                                //变,仍然是a =20 ,b = 10;
    int[] arr = {1,2,3,4,5};
    change(arr);//引用数据类型值传递,传入了地址
    System.out.println(arr[1]);//chage 方法中的arr变量和main方法中的arr变量指向的是同一片堆空间,所以在
                                 //change方法中做的修改,主方法中可以访问得到;arr[1] = 4;
}
public void change(int a,intb){
      a=b;
      b = b+a;
}
public void change(int[] arr){
   arr[1] = 4;
}
  • 基本数据类型的值传递,不改变原值,因为方法调用后就会弹栈,方法中的局部变量随之消失;
  • 引用数据类型的值传递,改变原值,因为即使方法弹栈,但是堆内存数组对象还在,可以通过地址继续访问;

问题: java中到底是传值还是传址?
1.既是传值,也是传地址,基本数据类型传递的是值,引用数据类型传递的是地址;
2.java中只有传值,因为地址值也是值;(出去面试说这种,java之父支持这种说法)