本文具体讲解了数组的界说、数组的访问方法、数组的遍历、静态数组和动态数组、以及数组中的自动范例转换、引用范例指向数组的地点、以及从JVM明白数组、空指针异常、数组反转、随机排名的案例。
数组是存放在连续内存空间上的类似范例数据的聚集。
数组可以方便的通过下标索引的方式获取到下标对应的数据。
举一个字符数组的例子,如图所示:
必要两点留意的是
- 数组下标都是从0开始的。
- 数组内存空间的地点是连续的
正是因为数组在内存空间的地点是连续的,以是我们在删除或者增添元素的时候,就难免要移动其他元素的地点。
一、数组的界说和访问
1.静态初始化数组
- 完整模式:
- 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3};
- int[] a = new int[]{1,2,3,4,5};
-
- 简化格式:
- 数据类型[] 数组名 = {元素1,元素2,元素3};
- double[] score = {85.5,75.5,90.5};
-
- 其他写法:
- 左边:数据类型[] 数组名 也可以写成 数据类型 数组名[]
- 源码中可能会看到这种写法。
-
复制代码
[重点]数组中的自动范例转换
虽然,数组只能生存类似数据范例的数据。
但,假如存储字符范例,编译的时候也不会报错。
- 我们知道byte、short、char能自动范例转换为int
- float能自动范例转换为double范例。
数组中也可以:
- int[] numbers = {10, (byte)20, (short)30, 'A'};
- // 等价于 {10, 20, 30, 65},自动转换为int
- double[] decimals = {1, 2.5f, 3L};
- // 等价于 {1.0, 2.5, 3.0},自动转换为double
复制代码
- System.out.println(Arrays.toString(ages1)); // 输出 [12, 24, 36, 65]
复制代码
二、数组在盘算机中的基本原理
数组是引用数据范例,存储数组在内存中的地点信息。
- int[] args = new int[]{1,2,3,4};
复制代码 [重点]这里args是一个数组的对象,数组是引用数据范例,存储数组在内存中的地点信息。
[重点]数组地点分析
打印出数组(引用数据范例)的地点。
[I@776ec8df]
//@ 占位符,读法at
//[ 数组
//I int
//776ec8df 内存地点
详情见:Java中的对象存储形式及控制台输出哈希码问题
回顾:
1.数组的静态初始化的写法和特点是什么?
- 我们再默写一遍
- 数据类型[] 数组名 = new 数据类型[]{1,2,3};
-
- 数据类型[] 数组名 = {1,2,3,4};
-
复制代码 如上,可以或许简写,或者源码写法。
2.界说数组我们说了那几个留意点?
1.什么范例的数组就存放什么样的数据。也有特例,不过能编译。一样平常,数组只能存储一种数据范例的数据
2.可以源码写法
3.数组属于什么范例?数组变量名中存储的是什么?
数组属于引用数据范例,存储的是数组在内存中的地点信息。
三、数组的访问
数组名称[索引]
数组的长度
数组名.length
[重点]末尾元素:数组名.length - 1的前提条件
- ArrayIndexOutOfBoundsException
复制代码 前提数组中的元素>0
回顾:
1.如何访问数组元素?
数字名[索引]
2.如何访问数组长度?
数组名.length
3.数组的最大索引/数组末尾元素是多少?
数组名.length -1
4.假如访问数组的时候,使用索引超过数组的最大索引会出现什么问题?
ArrayIndexOutOfBoundsException数组索引越界异常。
四、数组遍历
为什么,因为要进行数组元素的比较。
快捷键:args.fori,选择fori能自动快速生成遍历数组
案例-求和
- package com.itheima.array.define;
-
- public class ArrayTest4 {
- public static void main(String[] args) {
- // 某员工的销售额是16,26,36,6,100,请计算他们部门的总销售额。
- int[] arg = {16,26,36,6,100};
- // 求和思想:
- /*1.定义变量
- * 2.进行累加
- * */
- int sum = 0;
- for (int i = 0; i < arg.length; i++) {
- sum += arg[i];
- }
- System.out.println(sum);
-
- }
- }
-
复制代码
2.动态数组初始化
其实是没有规定元素是什么,而是规定元素的数据范例和个数。
- 数据类型[] 数组名 = mew 数据类型[元素个数];
- int args = new int[3];
复制代码 args[0] =10;//后赋值
我们知道,对象都存在于堆内存中,这里动态数组也是,存在堆内存中,直接打印数组,会出如今堆内存中的地点(哈希码形式)。
留意:
不要混了
[重点]动态初始化数组元素默认值规则:
分类数据范例默认值基本范例byte, short, char(Unicode是\u0000)显示空白字符, int, long0浮点型float, double0.0布尔型booleanfalse引用数据范例类, 接口, 数组, String等null 其实String也是对象。
留意boolean范例是false。
[重点]留意char数组的默认值为\u0000(Unicode空字符)对应的ASCII码值为0。控制台输出不是0
但直接打印时,\u0000不会显示为字符0,而是显示为“空白”(不可见字符)。
而是这个符号,代表Unicopde中的\u0000,不可见符号。
重点
- package com.itheima.array.define;
-
- public class ArrayDemo5 {
- public static void main(String[] args) {
- //注意char是Unicode编码(\u0000)
- char []arr = new char[3];
- System.out.println(arr[0]);
- System.out.println("===");
-
- int []arr1 = new int[3];
- System.out.println(arr1[0]);
- System.out.println("===");
-
- byte[]arr3 = new byte[3];
- System.out.println(arr3[0]);
- System.out.println("===");
-
- short[]arr2 = new short[3];
- System.out.println(arr2[0]);
- System.out.println("===");
-
-
- long[] arr31 = new long[3];
- System.out.println(arr31[0]);
- System.out.println("===");
-
- float[] arr4 = new float[3];
- System.out.println(arr4[0]);
- System.out.println("===");
-
- double[] arr5 = new double[3];
- System.out.println(arr5[0]);
- System.out.println("===");
-
- String[] arr6 = new String[3];
- System.out.println(arr6[0]);
- System.out.println("===");
- }
- }
-
复制代码
回顾:
1.动态初始化数组的写法是什么?
- 数据类型[] 数组名 = new 数据类型[长度];
- int [] args = new int[5]
复制代码
2.动态初始化数组的默认值是什么?
byte、short、int、char、long是0
float、double是0.0
boolean是false
String、类、接口、数组等引用数据范例是null。
3.两种数组界说的方法各自适用于什么业务场景?
静态初始化数组:适用于确定是数组元素的场景;
动态初始化:适用于只确定命组元素个数的场景
案例-求评委打分平均分
- package com.itheima.array.define;
-
- import java.sql.SQLOutput;
- import java.util.Scanner;
-
- public class ArrayTest5 {
- public static void main(String[] args) {
- //需求:现在有6个评委,给1名选手进行打分。请你求该选手的平均分
-
- //首先,数组存储
- //先解决单次一个人录入,然后存入数组
- //之后累加求和
- //最后求平均分sum/数组长度
-
- //完成单次录入
- /* int[] arr = new int[6];
- Scanner sc = new Scanner(System.in);
- arr[0]= sc.nextInt();
- System.out.println("第一个评委的打分是"+ arr[0]);*/
-
- int[] arr = new int[6];
- //改为多次录入ctrl+alt+t
- for (int i = 0; i < arr.length; i++) {//0-5索引
- // System.out.println("请输入" + (i + 1) + "个评委的打分");
-
- Scanner sc = new Scanner(System.in);
- arr[i] = sc.nextInt();
- System.out.println("第" + (i + 1) + "个评委的打分是" + arr[i]);
- }
- // 得到六个评委打分并存入数组
- //累加求和
- int sum = 0;
- //快捷键 arr.fori
- for (int i = 0; i < arr.length; i++) {
-
- sum += arr[i];
- }
- System.out.println("评委总分" + sum);
-
- //求平均分
- int avg = sum / arr.length;
- System.out.println("评委打分的平均分是" + avg);
- }
- }
-
复制代码
数组在盘算机中的执行原理
JVM的内存划分
方法区:加载字节码.class文件
栈内存:方法执行的时候进栈,方法中的变量存储也在栈内存。
堆内存:new出来的东西会在这块内存中开辟空间并产生地点。
讲解:
栈内存给main方法分配区域(栈帧)那么a就在栈内存中划分了一块区域,
执行打印,这里根据a找到区域,然后打印执行。
数组创建,那么就在堆内存中创建数组对象,数组对象也有地点,这个地点也会存到栈内存中。
通过arr存在栈内存的这个地点,找这个数组对象。
数组赋值之后真正产生变革的是堆内存的数据,而不栈中,栈中只有地点,
最后打印。
回顾:
方法区:执行class文件
执行方法,进入栈内存
new对象进入堆内存,
2.简单说说inta=20;int[]arr=new int[3]这两行代码的执行原理?
a是变量,直接放在栈内存中,a变量中存储的数据就是20这个值。
new int[3]是创建一个数组对象,会在堆内存中开辟区域存储3个整数。
[重点]案例:多个变量指向同一个数组
引用变量:引用数据范例的变量
1.多个变量指向同一个数组
引用变量arr1和arr2都是指向堆内存中同一个区域,那么其实赋值给arr2[1]==99;后修改的是堆内存中存储的数据。
2.赋值null
详见代码
- package com.itheima.memory;
-
- public class Demo1 {
- public static void main(String[] args) {
- //目标:多个变量指向同一个数组对象的执行原理
- //这个变量指的是引用变量,引用变量,就是引用数据类型的变量。数组就是引用数据类型
-
- //创建两个数组
- int arr1[] = {1,2,3};
- int arr2[] = arr1;//我们将arr1赋值给arr2,实际上是让 存在栈内存中的引用变量 指向 同一堆内存中的对象,也就是数组的元素。
- System.out.println(arr1);
- System.out.println(arr2);
- System.out.println("可以看到,两个数组的引用变量的地址是一致的,指向的是同一个堆内存中的区域");
- //如果我们修改arr2的一个元素,那arr1会改变吗?
- arr2[0] = 99;
- System.out.println(arr1[0]);//arr1也改变了
- System.out.println(arr1);
- System.out.println(arr2);//
- //以上,证明了arr1和arr2两个引用数据类型的变量,指向的是堆内存中的同一块区域,而且修改后同时发生改变。
-
- System.out.println("============【重点】如果赋值null===============");
- //2.如果赋值null
- arr2 = null;
- // System.out.println(arr2.length);
- System.out.println(arr1.length);
- System.out.println("编译不报错,因为arr2数组有length方法,输出arr2.length会运行报错");
- System.out.println("但是输出arr1.length不会报错,因为实际上修改的是引用变量arr2,arr1指向堆内存中的对象没有发生变化");
- }
-
- }
-
复制代码
执行过程图解:
[重点]空指针异常代表:引用数据范例的变量,该有东西,但是为空
[重点]回顾:
1.多个数组变量,指向同一个数组对象的缘故原由是什么?必要留意什么?
因为创建数组的时候,这两个引用数据范例变量,指向的都是同一个数组对象。存储的都是同一个数组对象的地点。
留意:多变量修改的都是同一个数组对象的数据。
2.假如某个数组变量中存储的null,代表什么意思?必要留意什么?
代表这个数组变量(引用范例变量),没有指向同一个对象。
可以输出这个变量,但是访问数组元素或获取数组长度,报NullPointerException
代码如下:
- package com.itheima.memory;
-
- public class Demo2 {
- //2.如果某个数组变量中存储的null,代表什么意思?需要注意什么?
- public static void main(String[] args) {
-
- int arr[] = new int[]{1,2};
- //引用变量赋值为null
- arr = null;
- System.out.println(arr);//可以打印出null
-
- int length1= arr.length;//访问数组长度:NullPointerException
- System.out.println(length1);
-
- int num = arr[0];//获取数组元素:NullPointerException
- System.out.println(num);
-
- }
-
- }
复制代码- [/code]
- 代码如下:
- [code]package com.itheima.memory;
-
- public class Demo1 {
- public static void main(String[] args) {
- //目标:多个变量指向同一个数组对象的执行原理
- //1.修改元素
- //这个变量指的是引用变量,引用变量,就是引用数据类型的变量。数组就是引用数据类型
-
- //创建两个数组
- int arr1[] = {1,2,3};
- int arr2[] = arr1;//我们将arr1赋值给arr2,实际上是让 存在栈内存中的引用变量 指向 同一堆内存中的对象,也就是数组的元素。
- System.out.println(arr1);
- System.out.println(arr2);
- System.out.println("可以看到,两个数组的引用变量的地址是一致的,指向的是同一个堆内存中的区域");
- //如果我们修改arr2的一个元素,那arr1会改变吗?
- arr2[0] = 99;
- System.out.println(arr1[0]);//arr1也改变了
- System.out.println(arr1);
- System.out.println(arr2);//
- //以上,证明了arr1和arr2两个引用数据类型的变量,指向的是堆内存中的同一块区域,而且修改后同时发生改变。
-
- System.out.println("============【重点】如果赋值null===============");
- //2.如果赋值null
- arr2 = null;
- // System.out.println(arr2.length);
- System.out.println(arr1.length);
- System.out.println("编译不报错,因为arr2数组有length方法,输出arr2.length会运行报错");
- System.out.println("但是输出arr1.length不会报错,因为实际上修改的是引用变量arr2,arr1指向堆内存中的对象没有发生变化");
- }
-
- }
-
复制代码
编译不报错,因为arr2数组有length方法,输出arr2.length会运行报错
但是输出arr1.length不会报错,因为实际上修改的是引用变量arr2,arr1指向堆内存
的对象没有发生变革。
[重点]案例,求数组元素中的最大值,最小值
要点:确定固定值max。以及。从第二个位置开始遍历元素。
1.起首用MAX变量作为数组中的一个元素,默认arr[0]。(就是一个平常的固定值,默以为0都可以)
2.从第二个位置开始遍历数组的元素,比较后,赋值到MAX变量中。因为是循环语句套在外面,跳出不了循环,那么会一直比较,全部的元素。大的就再次赋值,小的就继承循环。会直到循环竣事。
- package com.itheima.array;
-
- public class ArrayTest3 {
- public static void main(String[] args) {
- //数组,求最大值
- int arr[] = {1,2,3,4,5,5,6,7,8,10,6};
-
- int max = arr[0];//仅仅是一个固定值而已,赋值为数组中的一个元素,这样普遍性更强,否则如果是0,0可能是数组元素中最大或最小的。
- //arr.length-1 是指数组最后一个元素
- for (int i = 0; i < arr.length; i++) {
- if(max < arr[i]){
- max = arr[i];
- }
- }
- System.out.println(max);
- }
- }
-
复制代码
[重点]数组反转
int temp1 = arr1[0];//仅仅是一个固定值,这里赋值0也可以。表示成这样,方便阅读。
- package com.itheima.array.cases;
-
- public class Test2 {
- public static void main(String[] args) {
- //1.变量互换
- int a = 250;
- int b = 985;
- int temp = 0;
-
- temp = a;
- a = b;
- b = temp;
- System.out.println("a:" + a + "\n" + "b:" + b);
- System.out.println("======2.数组元素互换==============");
- //2.数组元素互换
- //让第一个和倒数第一个互换,第二个和倒数第二个互换,第三个和倒数第三个互换...
- int arr1[] = new int[]{10, 20, 30, 40, 50};
- int temp1 = arr1[0];//仅仅是一个固定值,这里赋值0也可以。表示成这样,方便阅读
- for (int i = 0, j = (arr1.length - 1); i < j; i++, j--) {//当i不小于j的时候进行结束,也就是刚好等于的时候
- //相当于变量互换
- temp1 = arr1[j];
- arr1[i] = arr1[j];
- arr1[i] = temp1;
- }
- //输出
- for (int i = 0; i < arr1.length; i++) {
- System.out.print(arr1[i] + "\t");
- }
- }
- }
-
复制代码
[难点]随机排名
- package com.itheima.array.cases;
-
- import java.util.Random;
- import java.util.Scanner;
-
- public class ArrayRandomRange_import_3 {
- public static void main(String[] args) {
- //非常熟练
- //需求:现在有五名创业者需要进行路演,他们分别有工号,但是为确保公平性,现在想随机上台路演。请你实现功能
- int c_num[] = new int[5];
- Scanner sc = new Scanner(System.in);
-
- //输入5个工号
- for (int i = 0; i < c_num.length; i++) {
- System.out.println("请你输入第"+(i+1)+"个工号");
- int num = sc.nextInt();
- c_num[i] = num;
- }
-
- //随机工号
- for (int j = 0; j < c_num.length; j++) {
- Random r = new Random();
- int ranDomIndex = r.nextInt(c_num.length);//nextInt()产生的是[0,4]与数组对应,不用[加减法]。
- //交换:(以随机索引的数组)=>数组的随机的另一个元素 与 本数组元素 按照迭代顺序交换。[首位呼应一条龙]
- //实际是:该数组的元素相互进行交换。
- //只是ranDomIndex是独立事件,会有重复数,会重复交换,导致随机的不是很彻底。
- int temp = 0;
- temp = c_num[j];
- c_num[j] = c_num[ranDomIndex];//先写,现在看就是数组俩元素进行交换,只是这个地方改成了ranDdonIndex
- c_num[ranDomIndex] = temp;
- }
-
- //输出
- for (int k = 0; k < c_num.length; k++) {
- System.out.print(c_num[k] +" ");
- }
- }
- }
-
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |