复习第二天第二部分数组

数组的概述

数组 : 数据的组合 (一组数据) -> 容器
​
变量也是容器,但是变量每次只能存储一个数据;若有批量同类型的数据,可以放入到数组中进行存储;
​
容器类型的知识点的学习方法:
    1. 如何创建容器 
    2. 掌握容器的增删改查四类功能 (CRUD)
    3. 遍历容器 -> 遍历: 依次从容器中取出容器中的每一个元素

数组的特点

1. 数组是Java引用数据类型中的一种!
    每当有数组被创建,那么一个数组类型的对象就产生了!!
2. 数组一旦被定义长度不能发生改变!如果数组的长度发生了改变,那么一定是创建新的数组! -> 弊端!
    //后期数组被集合取代(集合的长度是可变的),但是集合的底层其实还是数组!
3. 一个数组中的元素必须是同一数据类型; //方便管理 , 站在一个数组的角度
4. 数组中可以存储基本数据类型的元素和引用数据类型的元素;  -> 好处! 数组什么都能存!
        //宏观角度: 整个数组概念上!
5. 数组中的每一个元素都有一个 编号 : 专业叫 索引 -> 为了方便查询元素    
    索引是从0开始的,一个数组中最大的索引数: 长度-1
6. 数组有维度的概念 
    一维: 线段 :  线段是由一个个点来组成 
        一维数组 :  组成一维数组的元素,可以理解成组成线段的点
    二维: 面 : 面是由线段进行组成
        二维数组 : 一维数组中存储一维数组  // 不用花精力研究二维数组
        
举例:
    一维数组 : 一包烟
    二维数组 : 一条烟

数组的初始化

数组的动态初始化
    **数据类型[] 数组名 = new 数据类型[长度];
​
格式解释:
    数据类型 : 数组中元素的数据类型
    [] : 一维数组
    数组名 : 和变量名的作用一样,使用数组就是在使用数组的名字 -> 命名方式: 小驼峰
    = : 赋值运算符 把等号右边数组本体的地址赋值给左边的数组名 
    new : 创建对象(数组也是对象) / 在内存中开辟空间 (有空间就会有地址值)
    数据类型 : 数组中元素的数据类型 -> 要求前后的类型必须一致!
    长度 : 数组中元素的个数,数组的容量!    
​
数组的静态初始化 
    完整版格式 : 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,.....};
    **简化版格式 : 数据类型[] 数组名 = {元素1,元素2,元素3,.....};
​
格式解释:
    {元素1,元素2,元素3,.....} : 静态初始化会把数组中的元素一一罗列!
        
动静初始化数组的区别:
    动态初始化数据: 由程序员决定数组的长度/元素的个数,由计算机根据数组元素的数据类型来决定每一个元素的默认值(初始值)
        整数类型(byte,short,int,long) : 0
        浮点数类型(float,double) : 0.0
        字符类型(char) : 空字符 -> '\u0000'
        布尔类型(boolean) : false
        所有的引用数据类型数组 : null
    静态初始化数组: 由程序员决定每一个数组元素的具体值,由计算机自动计算数组的长度/元素的个数;
​
使用场景:
    动态: 程序员只知道容器的长度,而不知道容器中每一个元素的具体值,选择动态
    静态: 程序员明确的自动容器中每一个元素的具体值,选择静态
    
    
引用数据类型的对象和基本数据类型的变量的区别 :
    输出基本数据类型变量时 : 直接看到具体的数值 
    输出引用数据类型对象时 : 看到的是对象在内存中的地址值

数组的增删改查四类功能

数组的增删改查四类功能 :
    增 : 数组一旦被定义长度不能发生改变,没有增的功能!
    删 : 数组一旦被定义长度不能发生改变,没有删的功能!  
    改 : 先查后改
        **数组名[索引] = 要修改的值;
    查 : //利用数组中元素的索引来查找元素
        **数组名[索引] : 查询数组中指定索引位置上的元素值 (查: copy一份)
        //数组有长度属性    
        **数组名.length : 查询指定数组的长度/元素的个数    

数组的遍历标准代码

 //快捷代码: 数组名.fori 正序遍历  数组名.forr 倒序遍历
        for (int i = 0; i < arr1.length; i++) {
            System.out.println("arr1["+i+"] = " + arr1[i]);
        }''''
            

Java内存分配

栈内存 : stack
    作用1 : 给程序中方法执行提供内存空间
    作用2 : 存 局部变量的 //局部 : 方法内
    作用3 : 栈内存可以 表现 程序的执行流程  -> 方法进栈,方法出栈 
    
    栈内存的特点:
        1. 方法的进栈出栈 : 先进后出 -> 枪的弹夹
        2. 栈内存中的方法使用完毕立刻弹栈的
        
    StackOverFLowError : 栈内存溢出错误    
        //只能减少方法调用的次数 
​
堆内存 : memory -> 内存
    作用1 : 存储 new 出来的东西 -> 对象的本体都在堆中
    作用2 : 在JDK1.7之后常量池存储在堆内存中
    
    堆内存的特点:
        1. 只要在堆内存中开辟空间(创对象),堆内存就会给这个空间(对象)分配一个地址值
        2. 堆中对象内部的数据都有 默认值 -> 数组元素的默认值:
                    整数类型(byte,short,int,long) : 0
                    浮点数类型(float,double) : 0.0
                    字符类型(char) : 空字符 -> '\u0000'
                    布尔类型(boolean) : false
                    所有的引用数据类型数组 : null
        3. 堆内存中的对象使用完毕后,不是立即回收(死亡),而是等待 gc(垃圾回收机制) 空闲的时候回收    
            //能主动启动gc : System.gc() -> API
            
      OutOfMemoryError : 堆内存溢出错误
        //只能减少对象的创建次数
​
方法区 : 
    存储1. 字节码对象 (先编译(字节码文件 .class文件),再运行)
        // 一个类文件执行后,只可能生成一个字节码对象 --> 对象类型的校验
        // 字节码对象中 封装着 类的概览(目录) : 去反映一个类中有哪些成员(成员变量和成员方法)
        成员 : 表示一种位置关系 -> 在类中方法外
    存储2. 常量池 : 存储常量的内存容器   
        //常量池从JDK1.7开始 搬到了堆内存中
        
----------------------------------------------------------------        
本地方法区 : 本地方法执行的区域
    本地方法 : 和操作系统进行交互的方法 (本地方法在Java中会被 native 关键字修饰)
寄存器 : 和CPU的运算相关的板块

两个数组初始化的内存图

2个引用指向同一个内存地址: 任意一个引用修改内存区域,另一个引用也能看到内存数据的改变!!
​
操作对象的引用,本质上是操作对象在堆内存中的地址值!!

关于数组操作的2个小问题

    ArrayIndexOutOfBoundsException : 数组索引超出范围异常 -> 索引越界异常 //只能是数组里出现!
        产生的原因 : 访问了不存在的数组索引编号
        解决办法:
            1. 不访问
            2. 请使用正确的索引编号
            
    NullPointerException : 空指针异常  //只要是使用对象就可能出现此问题
        产生的原因:
            1. 使用了值为null的对象引用去访问了内部空间
            2. 使用了值为null的对象引用去访问了对象的属性
            3. 使用了值为null的对象引用去调用了对象的方法
            //不要去使用值为null的对象引用!!
       解决方案:
            1. 不使用值为null的对象
            2. 找到被使用的对象,查找这个对象什么时候被赋值为null, 修改此处代码给对象一个正确的地址值      

猜你喜欢

转载自blog.csdn.net/m0_70793154/article/details/127166122