Java中一维数组知识点【上课笔记详细】

关于一维数组

Array
1、Java语言中的数据是一种引用数据类型,不属于基本数据类型。数组的父类是Object
2、数据实际上是一个容器,可以同时容纳多个元素(元素是一个数据的集合。)
数组:字面意思是:一组数据
3、数据当中可以存储“几本书类型的数据”,也可以存储“引用数据类型”的数据
4、数组因为是引用数据类型,所以数组对象是堆内存中的(数组是存储在堆当中的)
5、数组当中如果存储的是java对象的话,实际上存储的是对象“引用(内存地址)”,数组当中不能直接存储java对象
6、数组一旦创建,在java中规定,长度不可变。(数组长度不可变)
7、数组的分类:一位数组,二维数组,三维数组,多维数组…(一维数组常用,二维数组偶尔使用)
8、所有数组对象都有length属性(java自带的),用来获取数组中元素的个数
9、java中的数组要求属猪中元素的类型要统一。比如int类型数组只能存储int类型,Person类型智能存储Person类型
10、数组中在内存方面存储的时候,数组当中的元素内存地址连续。内存地址连续,这是数据存储元素的特点,
11、所有的数组都是拿“第一个小方框的内存地址”作为整个数组对象的内存地址(数组中首元素的内存地址作为整个数组对象的)
12、数组中每一个元素都是由下表的,下标从0开始,以1递增,最后一个元素的下标是:length-1
下标非常重要,因为我们对象中元素进行“存取”时,都得通过下表
13、数组这种数据结构的优缺点是什么?
优点:查询/查找/检索某个下标上的元素试效率很高,可以说是查询效率最高的一个数据结构
为什么检索效率高?
第一:每一个元素在内存地址在空间上是联系的
第二:每一个元素类型相同,所以占用空间大小一样
第三:知道第一个元素的内存地址,知道每一个元素占用空间的大小,又知道下表,所以
通过一个数学表达式就可以计算出下表上的内存地址,直接通过内存地址定位元素,所以
数据的检索效率是非常高的
数组中存储100个元素,或者存储10000个元素,在元素查询/检索方面,效率是相同的
因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的。(算出一个内
存地址,直接定位)

缺点:
第一:由于为了保证每个元素的内存地址连续,所以在数据上随机删除或者增加元素的时候,
    效率较低,因为随机增删元素会涉及到后面元素统一向前或者向后位置的操作
第二:数组不能存储大数据量,为什么?
    因为很难再没存空间上找到一块特别大的连续的内存空间,
 注意:对数组最后一个元素的增删是没有影响的

14、怎么声明/定义一个一位数组?
语法格式:
int[] array1;
double[] array2;
boolean[] array3;
String[] array4;
Object[] array5;
15、怎么初始化一个以为数组呢?
包括两种方式:静态初始化一位数组,动态初始化一位数组。
静态初始化语法格式:
int[] array = {100,2100,300,55};
动态初始化语法格式:
int[] array = new int[5]; //这里的5表示数组的元素个数
//初始化一个5个长度的int类型数组,每个元素默认值0
String[] names = new String[6]; //初始化6个长度的String类型数组,每个元素默认值null

1.一维数组的取、存和遍历

1.1代码展示

package com.power.Javase.array;
public class ArrayTest01 {
    public static void main(String[] args) {
        //声明一个int类型的数据,使用静态初始化的方式
        int[] a = {1,2,6,85,20,12};

        //所有的数组对象都有length属性
        System.out.println("数组中元素的个数" + a.length);

        //数组中每一个元素都有下标
        //通过下表对数组中的元素进行存和取
        //取
        System.out.println("第一个元素 =" + a[0]);
        System.out.println("最后一个元素 =" + a[5]);
        System.out.println("最后一个元素 =" + a[a.length - 1]);

        //存(改)
        a[0] = 111;
        a[a.length - 1] = 0;
        System.out.println("第一个元素 =" + a[0]);
        System.out.println("最后一个元素 =" + a[5]);

        //一维数组怎么遍历呢?
        for(int i=0;i<a.length;i++){
            System.out.println(a[i]);
        }

        //下标为6表示第7个元素,第7个元素没有,下标越界了,会出现什么异常呢?
        //ArrayIndexOutOfBoundsException(比较著名的异常)

        //从最后一个元素遍历到第一个元素
        for(int i = a.length - 1;i>=0; i++){
            System.out.println(a[i]);
        }
    }
}

1.2执行结果

在这里插入图片描述

1.3内存结构图展示

在这里插入图片描述

示例二:
什么时候采用静态初始化方法,什么时候采用动态初始化方法?
当你创建数组的时候,确定数组中存储的哪些具体的元素时,采用静态初始化方式
当你创建数组的时候,不确定将来数组中存储那些数据,你可以采用动态初始化的方式,预先分配内存空间

2.初始化一位数组

2.1 2.初始化一位数组

public class ArrayTest02 {
    public static void main(String[] args) {
        //声明/定义一个数组,采用动态初始化方式创建
        int[] a = new int[4]; //创建长度为4的int数组,数组中每个元素默认值是0
        //遍历数组
        for(int i = 0;i<a.length;i++){
            System.out.println("数组中下标为:" + i+ "的元素是:" + a[i]);
        }
        //后期赋值
        a[0] = 8;
        a[1] = 25;
        a[2] = 34;
        a[3] = 41;

        //初始化一个Object类型的数组,采用动态初始化方式
        Object[] objs = new Object[3]; //3个长度,动态初始化,所以每个元素默认值是null
        for(int i = 0; i < objs.length;i++){
            System.out.println(objs[i]);
        }
        System.out.println("====================================");

        String[] str = new String[3];
        for(int i = 0; i<str.length;i++){
            System.out.println(str[i]);
        }

        //采用静态初始化的方式
        String[] str2 ={"abc","def","xyz"};
        for(int i=0; i<str2.length;i++){
            System.out.println(str2[i]);
        }

        //存储Object,采用静态初始化呢?
        Object o1 = new Object();
        Object o2 = new Object();
        Object o3 = new Object();
        Object[] objects = {o1,o2,o3};
        for(int i =0;i<objects.length;i++){
            System.out.println(objects[i]);
        }
    }
}

2.2执行结果:

在这里插入图片描述

2.3内存结构图展示

在这里插入图片描述

3方法的参数是数组(1)

3.1代码展示:

数组类型作为这个方法体的参数
(1)

 public static void printArray(int[] array) {
        for (int i=0;i<array.length;i++){
            System.out.println(array[i]);
        }
    }

(2)

public static void printArray(String[] array) {
     for (int i = 0; i < array.length; i++) {
         System.out.println(array[i]);
     }
 }

完整代码如下:

package com.power.Javase.array;

public class ArrayTest03 {
    public static void main(String[] args) {
        System.out.println("hello world!");

        int[] a1 = {12,45,63};
        for (int i = 0; i<a1.length;i++){
            System.out.println(a1[i]);
        }
        System.out.println("===================================");

        //创建int数组
        int[] x = {1,2,3,4};
        printArray(x);

        //创建String数组
        String[] str =  {"abc","def","haha","lala"};
        printArray(str);

        String[] str2 = new String[10];
        printArray(str2);

    }


    public static void printArray(int[] array) {
        for (int i=0;i<array.length;i++){
            System.out.println(array[i]);
        }
    }
    public static void printArray(String[] array) {
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}

3.2执行结果

在这里插入图片描述

4方法的参数是数组(2)

4.1代码展示

(1)

int[] a2 = new int[4];
        printArray(a2);

(2)

printArray(new int[3]);

对于动态初始化数组来说,我们可以看出(1)和(2)本质上其实是一样的都是创建了一个数组类型的对象。

(3)
没有这种语法

没有这种语法
        printArray({1,2,3});

(4)
如果直接传递一个静态数组的话,语法必须这样写:

如果直接传递一个静态数组的话,语法必须这样写:
	printArray(new int[]{1,2,3});
package com.power.Javase.array;
//当一个方法的参数是一个数据的时候,我们还可以采用这种方式传

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.util.jar.JarOutputStream;

public class ArrayTest04 {
    public static void main(String[] args) {
        //静态初始化一位数组
        int[] a = {1,2,3,4};
        printArray(a);

        System.out.println("=====================================");
        //没有这总这种语法
        //printArray({1,2,3});
        //如果直接传递一个静态数组的话,语法必须这样写:
        printArray(new int[]{1,2,3});


        //动态初始化一位数组
        int[] a2 = new int[4];
        printArray(a2);

        System.out.println("=========================================");
        printArray(new int[3]);
    }

    public static void printArray(int[] array) {
        for(int i=0;i<array.length;i++){
            System.out.println(array[i]);
        }
    }
}

4.2执行结果

在这里插入图片描述

5.main方法的String[ ]数组

你有没有疑问过为什么主函数最后部分要写上String[] args,原来它本质上也是一个数组,在DOS窗口手动传入参数之后就会自动到这个数组中,可以用数组自带的长度函数来进行验证

//这个数组什么时候里面会有值呢?
//其实这个数字是留给用户的,用户可以在控制台上输入参数,这个参数自动回复被转换为“String[] args”
//例如这样与奴性程序:java ArrayTest05 abc def xyz
//那么这个时候JVM会自动将“abc def xyz”通过空格的方式进行分离,分立完成之后,自动放到“String[] args”数组
//所以main方法上面的String[] args数组主要是用来接受用户输入参数二代
//把abc def xyz 转换成字符串数组;{“abc”,“def”,“xyz”}
//遍历数组

核心代码

public static void main(String[] args) {
        //JVM默认传递过来的这个数组对象的长度?默认0
        //通过测试得出:args不是null
        System.out.println("JVM给传递过来的String数组参数,它这个数组长度是?" + args.length);

5.1代码展示


/*
1、main方法上面的“String[] args”有什么用?
    分析如下:谁负责调用main方法(JVM)
    JVM调用main方法的时候,会自动传一个String数组过来
 */
public class ArrayTest05 {
    //这个方法程序员负责写出来,JVM负责调用。JVM负责调用一定会传一个String数组过来
    public static void main(String[] args) {
        //JVM默认传递过来的这个数组对象的长度?默认0
        //通过测试得出:args不是null
        System.out.println("JVM给传递过来的String数组参数,它这个数组长度是?" + args.length);

    //以下这一行代码表示的含义:数据对象创建了,但是数组中,诶有任何数据
    //String[] strs = new String[0];
    //String[] strs = {};     //静态初始化数组,里面没东西
    //printLength(strs);



    //这个数组什么时候里面会有值呢?
    //其实这个数字是留给用户的,用户可以在控制台上输入参数,这个参数自动回复被转换为“String[] args”
    //例如这样与奴性程序:java ArrayTest05 abc def xyz
    //那么这个时候JVM会自动将“abc def xyz”通过空格的方式进行分离,分立完成之后,自动放到“String[] args”数组
    //所以main方法上面的String[] args数组主要是用来接受用户输入参数二代
    //把abc def xyz 转换成字符串数组;{“abc”,“def”,"xyz"}
    //遍历数组
    for(int i = 0;i < args.length; i++){
        System.out.println(args[i]);
    }
}
    public static void printLength(String[] args) {
        System.out.println(args.length);
    }
}

5.2执行结果

在DOS窗口手动传值,传入的值都将保留到main方法的String[ ]数组中
在这里插入图片描述

6.main方法的String[ ]数组

注意代码:

username.equals("admain")&& password.equals("123")

使用以下这种编码风格,即使username和password都是null,也不会出现空指针异常
因为调用的是”admin“的equals方法

if("admain".equals(username)&& "123".equals(password)){

6.1代码展示


/*
* 模拟一个系统,假设而这个系统要使用,必须输入用户名和密码
*/
public class ArrayTest06 {
    //用户名和密码输入到String[] args数组当中
    public static void main(String[] args) {
        if(args.length !=2){
            System.out.println("使用该系统时输入程序参数,参数中包括用户名和密码信息,例如:zhangsan 123");
            return;
        }

        //程序执行到此处说明用户确实提供了用户名和密码
        //接下来你应该判断用户名和密码是否正确
        //取出用户名
        String username = args[0];

        //取出密码
        String password = args[1];

        //假设用户名数admain,密码是123的时候表示登陆成功。其它一律失败
        //判断两个字符是否相等,需要使用equals方法
        if(username.equals("admain")&& password.equals("123")){
            System.out.println("登陆成功,欢迎" + username + "回来");
            System.out.println("您可以继续使用该系统");
        }else{
			System.out.println("验证失败,用户名不存在或者密码错误");
		}
    }
}

6.2执行结果

在这里插入图片描述

7.main方法的String[ ]数组

核心代码:
1.可以看(1)和(2)是一样的,(2)是在(1)的基础之上将代码合并
(1)

			Animal a = animals[i];
            a.move();

(2)

 //代码合并
            animals[i].move();  //这个move()方法不是数组的,是数组当中Animal对象的move()方法

2.同理,可以看出(3)和(4)是一样的,(4)是将(3)代码合并
(3) //创建一个Animal类型的数组,数组当中存储Cat和Bird

 //创建一个Animal类型的数组,数组当中存储Cat和Bird
        Cat c = new Cat();
        Bird b = new Bird();
        Animal[] anis ={c,b};

(4)

 Animal[] anis = {new Cat[];new Bird[]};   //该数组存储量两个对象的内存地址

3.具有继承关系的数据类型引用时需要注意的问题?
(5)这个取出来的可能是Cat,也可能是Bird,不过肯定是一个Animal,如果调用的方法是父类中
存在的方法不需要向下转型,直接使用父类型引用调用即可

//这个取出来的可能是Cat,也可能是Bird,不过肯定是一个Animal
            //如果调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
            Animal an = anis[i];
           an.move();

(6)调用子类特有对象时,需要向下转型

if(anis[i] instanceof Cat){
                Cat cat =(Cat)anis[i];
                cat.catMouse();

            }else if(anis[i] instanceof Bird){
                Bird bird = (Bird)anis[i];
                bird.sing();
            }

7.1代码展示

package com.power.Javase.array;
/**
 * 一维数组的深入,数组中存储的类型为:引用数据类型
 * 对于数组来说,实际上只能存储java 对象的内存地址,数组中存储的每个元素的引用
 */
public class ArrayTest07 {
    public static void main(String[] args) {

        int[] array = {1,2,3};
        for(int i=0;i<array.length;i++){
            /*int temp = array[i];
            System.out.println(temp);*/  //简单理解为拿过来赋给变量
            //代码合并
            System.out.println(array[i]);

        }

        //创建一个Aminal类型的数组
        Animal a1 = new Animal();
        Animal a2 = new Animal();
        Animal[] animals = {a1,a2};

        //对Animal数组进行遍历
        for(int i =0; i <animals.length;i++){
            /*Animal a = animals[i];
            a.move();*/
            //代码合并
            animals[i].move();  //这个move()方法不是数组的,是数组当中Animal对象的move()方法
        }

        //动态初始化一个长度为2的animal数组
        Animal[] ans = new Animal[2];
        //创建一个Animal对象,放到数组的第一个盒子中
        ans[0] = new Animal();

        //Animal数组中只能存放Animal类型,不能存放Product类型
        //ans[1] = new Product();

        //Animal数组中可以存放Cat类型的数据,
        //Cat是Animal的子类,因为Cat是一个Animal。
        ans[1] = new Cat();

        //创建一个Animal类型的数组,数组当中存储Cat和Bird
        Cat c = new Cat();
        Bird b = new Bird();
        Animal[] anis ={c,b};

       //Animal[] anis = {new Cat[];new Bird[]};   //该数组存储量两个对象的内存地址
        for(int i = 0; i < anis.length; i++){
            //这个取出来的可能是Cat,也可能是Bird,不过肯定是一个Animal
            //如果调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
            //Animal an = anis[i];
            //an.move();

            //调用子类特有对象时,需要向下转型
            if(anis[i] instanceof Cat){
                Cat cat =(Cat)anis[i];
                cat.catMouse();

            }else if(anis[i] instanceof Bird){
                Bird bird = (Bird)anis[i];
                bird.sing();
            }
        }


    }
}
class Animal{
    public void move(){
        System.out.println("Animal move...");
    }
}

//s商品类
class Product{

}

//Cat是子类
class Cat extends Animal{
    public void move(){
        System.out.println("猫在走猫步");
    }
    //特有方法
    public void catMouse(){
        System.out.println("猫抓老鼠");
    }
}
//Bird子类
class Bird extends Animal{
    public void move(){
        System.out.println("Bird fly");
    }
    public void sing(){
        System.out.println("鸟儿在唱歌");
    }

}

7.2执行结果

在这里插入图片描述

8.数组的扩容

关于一位数组的扩容
在java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
数组满了,需要扩容
java中对数组的扩容是:
先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组中

结论:数组库哦哦让效率比较低。因为涉及到拷贝的问题。所以在以后的开发中请注意,尽可能少的进行数组的拷贝
可以在创建数组对象的时候预估计以下多长合适,最好与古尊却,这样可以减少数组的扩容次数,提高效率

8.1代码展示

package com.power.Javase.array;
/*
关于一位数组的扩容
在java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
    数组满了,需要扩容
    java中对数组的扩容是:
    先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组中

  结论:数组库哦哦让效率比较低。因为涉及到拷贝的问题。所以在以后的开发中请注意,尽可能少的进行数组的拷贝
  可以在创建数组对象的时候预估计以下多长合适,最好与古尊却,这样可以减少数组的扩容次数,提高效率
 */

public class ArrayTest08 {
    public static void main(String[] args) {
        //java中的数据怎么进行拷贝呢?
        //System.arraycopy();

        //拷贝源(从这个数组中进行拷贝)
        int[] src = {1, 11, 22, 3, 4};

        //拷贝目标(拷贝到这个目标数组上)
        int[] dest = new int[20];

      /*  //调用JDK System类中的arraycopy犯法,来完成数组的拷贝
        System.arraycopy(src,1,dest,3,2);

        //遍历目标数组
        for(int i = 0;i < dest.length;i++){
            System.out.println(dest[i]); //0 0 0 11 22 ... 0
        }
      */
        System.arraycopy(src, 0, dest, 0, src.length);
        for (int i = 0; i < dest.length; i++) {
            System.out.println(dest[i]);  //
        }

        /*
        //数组中如果有存储的元素是引用,可以存储吗?当然可以
        String[] strs = {"hello", "world", "study", "java", "oracle", "aysql", "javase"};
        String[] newStrs = new String[20];
        System.arraycopy(strs, 0, newStrs, 0, strs.length);
        for (int i = 0; i < newStrs.length; i++) {
            System.out.println(newStrs[i]);
        }*/

        System.out.println("================================");
        Object[] objs ={new Object(), new Object(), new Object()};
        Object[] newObjs = new Object[5];
        //思考一下,这里的拷贝的时候是拷贝到是对象还是拷贝的地址(答案:地址)
        System.arraycopy(objs,0,newObjs,0,objs.length);
        for(int i=0;i<newObjs.length;i++){
            System.out.println(newObjs[i]);
        }
    }
}

8.2执行结果

在这里插入图片描述

8.2内存展示

(1)
在这里插入图片描述

(2)

在这里插入图片描述
(3)
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值