Java基础语法(六) 您所在的位置:网站首页 java怎么定义一个字符 Java基础语法(六)

Java基础语法(六)

2023-09-30 22:49| 来源: 网络整理| 查看: 265

本次内容介绍大纲

在这里插入图片描述在这里插入图片描述

接上篇博客 Java基础语法(五)——方法的使用

Java基础语法(六)——数组的定义与使用一、 数组基本用法1.什么是数组

  数组本质上就是让我们能 “批量” 创建相同类型的变量.

例如:

如果需要表示两个数据, 那么直接创建两个变量即可 int a; int b

int a = 10; int b = 20;

如果需要表示五个数据, 那么可以创建五个变量 int a1; int a2; int a3; int a4; int a5;

int a1 = 10; int a2 = 20; int a3 = 30; int a4 = 40; int a5 = 50;

  但是如果需要表示一万个数据, 那么就不能创建一万个变量了. 这时候就需要使用数组, 帮我们批量创建.

int[] array = {10,20,30,40,50};

上面就是整型数组.

注意事项: 在 Java 中, 数组中包含的变量必须是 相同类型.

2. 创建数组

基本语法

在这里插入图片描述在这里插入图片描述

  在上面的实例中,我们就以整型数组为例,创建了一个 int [ ] 类型的array数组,并且存放了5个整形数据.讲解了数组创建时的用法,Java数组的创建与C语言很是相似,但是还是有区别的.

C语言版本数组的创建:

int arr[5] = {1,2,3,4,5};

Java版本数组的创建:

int[] arr = {1,2,3,4,5};

  我们可以通过两种写法看到其中的区别. Java当中一定要 [ ] 和数据类型紧挨在一起.

  数组的数据在内存中是连续存放的.继续以上面的代码为例:

在这里插入图片描述在这里插入图片描述

  数组的每一元素都有其对应的下标,而下标->从0开始,我们要想找到这个数组中的某个数据,是通过数组的下标来进行访问的.

注意:

数组也被称为存放一组相同类型的数据的集合!!

下标是从0号位置开始的.

3.定义数组的方式

定义方式一

在这里插入图片描述在这里插入图片描述

  上面我们写的代码是,定义并初始化了一个数组.

在这里插入图片描述在这里插入图片描述

  这样的方式才只是定义了一个数组.这就是我们定义数组的第一种方式.且这样定义的数组默认大小为0.

定义方式二

在这里插入图片描述在这里插入图片描述

  这样也是定义了一个数组,不过这个数组定义是通过new 这样一个关键字,给 array 分配了一块内存,这块内存有10个数据可以存放.

在这里插入图片描述在这里插入图片描述

  int [ 10 ] 分配的连续内存空间.

  不过此时,我们还未给 array 这个数组进行初始化,所以 array 此时的这十个数据默认值为0.

定义方式三

在这里插入图片描述在这里插入图片描述

  在Java当中在已经初始化之后, = 左边的 [ ] 中是不能填数字的, = 右边的 [ ] 只有在 定义方式二 中可以给定值.

在定义方式三中

在这里插入图片描述在这里插入图片描述

总结定义数组的三种方式:

int[] array1 = {1,2,3,4,5}; // 定义一 int[] array2 = new int[10]; // 定义二 int[] array3 = new int[]{1,2,3,4,5}; // 定义三

在这三种方式中,Java中定义数组最常用的是方式一。

4. 数组的使用(1)获取长度

注意事项

使用 arr.length 能够获取到数组的长度. . 这个操作为成员访问操作符. 后面在面向对象中会经常用到

代码示例:

public static void main(String[] args) { int[] array = {1,2,3,4,5}; System.out.println(array.length); }

编译结果:

在这里插入图片描述在这里插入图片描述(2)访问数组中的元素

数组访问的方式:

在这里插入图片描述在这里插入图片描述

注意事项:

使用 [ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数

使用 [ ] 操作既能读取数据, 也能修改数据.

下标访问操作不能超出有效范围 [0, length) , 如果超出有效范围, 会出现下标越界异常

代码示例:

public static void main(String[] args) { int[] array = {1,2,3,4,5}; //获取数组中的元素的个数 //System.out.println(array.length); //访问数组中的元素 System.out.println(array[1]); // 执行结果: 2 System.out.println(array[2]); // 执行结果: 3 //修改数组中的元素 array[2] = 100; System.out.println(array[2]); // 执行结果: 100 }

编译结果:

在这里插入图片描述在这里插入图片描述(3)下标越界

  数组下标从0开始,范围是 [0,arr.length) ,左闭右开的区间,或者是[ 0,arr.length-1].

  如果我们将下标的值超出数组的范围…

如下所示

public static void main(String[] args) { int[] arr = {1,2,3,4,5,6}; System.out.println(arr[100]); }

编译结果:

在这里插入图片描述在这里插入图片描述(4)遍历数组

  所谓 “遍历” 是指将数组中的所有元素都访问一遍, 不重不漏. 通常需要搭配循环语句

1.遍历方式(一)-----for循环

public static void main(String[] args) { int[] arr = {1, 2, 3}; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } }

编译结果:

在这里插入图片描述在这里插入图片描述

  我们可以看到,用 for 循环 将数组中的元素一 一遍历 并打印出来.

2.遍历方式(二)---->for-each

  for-each 是 for 循环的另外一种使用方式. 能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错.

for-each 的基本使用

在这里插入图片描述在这里插入图片描述

代码示例:

public static void main(String[] args) { int[] arr = {1,2,3,4,5}; for (int x:arr) { System.out.print(x+" "); } }

编译结果:

在这里插入图片描述在这里插入图片描述

for-each 遍历的原理

  遍历array 里面的每一个元素,把每一个元素取出来,然后赋值给了 x ,最后打印 x ,直到 array 里面的元素全部都遍历完成.

两种遍历的方式我们介绍完了,那么for循环和for-each有什么区别?

  for循环是可以拿到数组下标的,for-each拿不到数组下标,所以for-each只能够全部遍历,无法对数组元素进行修改或进行操作.

3.遍历方式(三)——使用操作数组的工具类进行数组的打印

  Arrays 就是操作Java数组的工具类,你要对数组做什么事情,就可以通过他来做,当然有些事情他是完成不了的.

  比如说:我们要打印数组,我们本来是用for循环 或者 for-each 来写的,但是我们也可以用Arrays的工具类打印.

  通过JDK的工具文档,我们查找到了相应的工具类.

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  好,我们对arr数组进行操作如下:

public static void main(String[] args) { int[] arr = {1,2,3,4,5}; System.out.println(Arrays.toString(arr)); }

编辑结果:

在这里插入图片描述在这里插入图片描述5.数组在内存中的存储

  我们在之前的博客已经很简单介绍了Java中的内存区域划分,那么今天我们认识了数组这个引用类型,那么它在内存中如何进行存储呢?

  我们先简单回顾一下Java的内存区域

在这里插入图片描述在这里插入图片描述

  我们知道局部变量都在Java虚拟机栈上存放,而数组的数据则在堆上进行存放, 数组的数据在堆上都有特定的地址,而数组的变量存放的其实是这组数据的地址,栈上的这个变量根据这个地址找到堆上的数据.

  数组的具体存储由下图所示:

在这里插入图片描述在这里插入图片描述

注意点:

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  上图为arr指向的数据在堆中的地址,这个地址并不是真正的地址,它是通过正式的地址 hash 得到的.但是我们可以把它当作真实的地址,因为这个地址也是唯一的.

  那么真实的地址为什么要hash操作呢?

  这就是Java的安全性了,不会轻易暴露自己数据的地址.

二、数组作为方法的参数1.基本用法

代码示例: 打印数组内容

public static void main(String[] args) { int[] arr = {1, 2, 3}; printArray(arr); } public static void printArray(int[] a) { for (int x : a) { System.out.println(x); } }

在这个代码中

1.int [ ] a 是函数的形参, int [ ] arr 是函数实参.

2.如果需要获取到数组长度, 同样可以使用 a.length

2.理解引用类型

  在上一期博客 方法的使用中 ,我们介绍了一个用方法来交换两个变量 的具体情况.现在我们来回顾一下.

(1)参数传内置类型在这里插入图片描述在这里插入图片描述

  我们用 内置类型作为参数,进行交换变量,但是最后编译的结果 两个变量却并未发生交换.

  这是为什么呢?

在这里插入图片描述在这里插入图片描述

  交换形参 的值, 不影响实参的 值.

(2)参数传数组类型在这里插入图片描述在这里插入图片描述

  我们用 数组作为参数,进行交换变量,编译运行后,发现成功交换两个变量的值。此时数组名 arr 是一个 “引用” . 当传参的时候, 是按照引用传参.

  那么为什么传引用类型可以 形参可对实参进行操作呢?

  这里我们就要先从内存说起

  在上面我们介绍了数组在内存中的储存,

在这里插入图片描述在这里插入图片描述

  我们可以知道,数组这个在栈中存放的变量实际存放的是 堆中数据的地址,当我们 arr 数组作为参数 传入 方法里,我们就把 堆中数据的地址 传入了进去,在方法内部,我们可以根据 这个地址 找到堆中的数据进而修改数据,从而实现了形参改变了实参的操作.

在这里插入图片描述在这里插入图片描述

总结:

  所谓的 “引用” 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大).

3.认识 null

  引用类型的0值 就是 null.

在这里插入图片描述在这里插入图片描述

  当我们将 null 赋给arr 这个引用类型时,这又是什么意思呢?

代表 arr 这个引用,不指向任何对象.

  当我们运行这个代码时,显示的结果就是 null ,不是数值 0.

在这里插入图片描述在这里插入图片描述

  那我们再来看一个问题

  当我们将 null 赋给 arr 之后,那么arr 数组的长度是多少呢?

  我们猜测可能为0,现在来运行代码.

  运行结果如下:

在这里插入图片描述在这里插入图片描述

  此时,编辑器报错,错误类型:空指针异常.

  好了,这时我们可以知道,null 赋给了 arr ,arr 没有指向任何一个数组对象,在堆上也没有开辟内存空间,所以我们也就无法求它的长度.

总结:

null.任何东西,都会发生 空指针异常的错误.

经验:只要以后出现这样的异常,肯定是这一个引用是 null.

4.初识JVM内存区域划分

一个宿舍楼会划分成几个不同的区域: 大一学生, 大二学生… 计算机专业学生, 通信专业学生…

内存也是类似, 这个大走廊被分成很多部分, 每个区域存放不同的数据.

JVM 的内存被划分成了几个区域, 如图所示:

在这里插入图片描述在这里插入图片描述

程序计数器 (PC Register):

只是一个很小的空间, 保存下一条执行的指令的地址.

虚拟机栈(JVM Stack):

重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] arr 这样的存储地址的引用就是在这里保存.

本地方法栈(Native Method Stack)

本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.

堆(Heap):

JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )

方法区(Method Area):

用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.

运行时常量池(Runtime Constant Pool):

是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从JDK1.7 开始, 运行时常量池在堆上)

  关于上面的划分方式, 我们随着后面的学习慢慢理解. 此处我们重点理解 虚拟机栈 和 堆.

在这里插入图片描述在这里插入图片描述

1.局部变量和引用保存在栈上, new 出的对象保存在堆上.

2.堆的空间非常大, 栈的空间比较小.

3.堆是整个 JVM 共享一个, 而栈每个线程具有一份(一个 Java 程序中可能存在多个栈).

三、数组作为方法的返回值

代码示例:

public static void main(String[] args) { int[] arr = {1, 2, 3}; transform(arr); printArray(arr); } public static void printArray(int[] arr) { for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } public static void transform(int[] arr) { for (int i = 0; i < arr.length; i++) { arr[i] = arr[i] * 2; } }

  这个代码固然可行, 但是破坏了原有数组. 有时候我们不希望破坏原数组, 就需要在方法内部创建一个新的数组, 并由方法返回出来。

  修改后的代码:

public static void main(String[] args) { int[] arr = {1, 2, 3}; int[] output = transform(arr); printArray(output); } public static void printArray(int[] arr) { for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } public static int[] transform(int[] arr) { int[] ret = new int[arr.length]; for (int i = 0; i < arr.length; i++) { ret[i] = arr[i] * 2; } return ret; }

  这样的话就不会破坏原有数组了.

  另外由于数组是引用类型, 返回的时候只是将这个数组的首地址返回给函数调用者, 没有拷贝数组内容, 从而比较高效。

四、数组练习1.数组转字符串

题目要求:

实现一个方法 toString, 把一个整型数组转换成字符串.

例如数组 {1, 2, 3} , 返回的字符串为 “[1, 2, 3]”, 注意 逗号 的位置和数量.

public static String mytoString(int[] arr){ String ret = "["; for (int i = 0; i max) { max = arr[i]; } } return max; } public static void main(String[] args) { int[] arr={10,20,900,40,100,500}; int ret = findMax(arr); System.out.println(ret); }4.求数组中元素的平均值

题目内容

给定一个整型数组, 求平均值

代码实现:

public static double aver(int[] arr){ int sum = 0; for (int i = 0; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有