004-Java方法和数组

undefined

第三章 方法和数组

3.1 概述

还记得我们的HelloWorld例程吗?我们现在对于输出语句应该已经很熟悉了,

解释:

System 是系统类。

out 是标准输出对象

println() 是一个方法。

如果我们想要在一个类中实现很多功能,但是如果我们想要,多次使用,某一个功能,显然我们需要重复书写这个功能的代码多次,显然,这是不明智的。所以方法就来拯救我们了。

❤ 3.1_1方法的基本定义

定义:方法是定义在类中的一段独立的代码块,用来实现某个功能。

其实我们在编程界中更喜欢叫它们为函数,但是在Java中我们也可以叫做方法

作用:

·函数的主要作用是为了提高代码的复用性。

·使程序简短而清晰,更加利于维护

img

A:修饰符: public static (暂时了解这一个 后期补充)

B:返回值类型: 就是功能结果的数据类型

有一些方法执行代码中的命令即可,执行后就可以结束了,并没有返回值(void)

有一些方法需要将最后的结果返回给你,从而让开发者使用这个结果

举例更好理解哦:最近有一场周杰伦的演唱会,我通过好多朋友帮忙一起的抢票方法,最后得到了两张票,这两张票就是“抢票”方>法的返回值,我(开发者)可以对这个返回值进行任何操作,例如自己去看,或者送给朋友,甚至可以用来当草稿纸(哭…)

C:参数类型:参数的数据类型

主方法可以调用其他方法,其他方法可以互相调用,但不能调用主方法,主函数是系统调用的。

❤ 3.1_方法(函数)的调用方法:

A:单独使用,一般来说没有意义(不代表有错),所以不推荐

B:输出调用,但是不够好,因为我们可能需要针对结果进行进一步操作

C:赋值语句,推荐方案。

方法的调用优化:

Eg:比较两个数是否相等(在没有熟练之前我们仍然推荐使用初始直观的用法,程序可以正常的跑是我们的底线)

❤ 3.1_3 方法重载

一般来说,我们都是根据作用来命名方法(方法名有意义),但是很多时候会我们会针对不同的数据类型,或者参数个数来进行操作,例如我们所要求几个数字中的最大值问题(如下图)就出现了这两种问题。使用方法重载,既可以保证命名有意义,也可以避免记忆过多的不同名称

定义:用同一方法名定义多个方法,这些方法的参数个数或者参数类型不同

作用:使一个方法名赋予新的含义,使一个方法名可以多用

适用:实现细节不同的同一类功能时候

理解:其实就是使得一个方法拥有了更多的可能性,一个名称解决多种问题。

注意:

  1. 函数的返回类型不同,但参数个数和类型相同,不是重载

  2. 重载函数的的参数个数,参数类型,参数顺序至少有一个需要不同

3.2数组

引文:我们在篮球场比赛中,梦之队运动员共有10名,我们分别将每个人定义为几号运动员,这样我们找某一个人的时候,我们就会先找到梦之队这支队伍,然后去找对应编号的人。
而数组就像这只队伍的概念一样,而数组中的每一个元素就是每一个球员,当你需要找数组的某一个元素的时候,只需要找到你需要查找的数组(梦之队),再根据数组下标(对应编号)去寻找对应元素(球员)。
这样做的好处就是,我们将一批同类型的元素整理归纳到了一起,并且标号记录。
既方便了查找与使用,又避免了定义多个变量的麻烦。
概念:以存储一个固定大小的相同类型元素的顺序集合。

数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。

(所有的数组都是由连续的内存位置组成)

格式:

第一种读法:定义一个 dataType类型的数组 arrayRefvar 变量

第一种可以认为是java风格的定义格式,推荐第一种,不过也只是编程风格不同罢了。

初始化:

  • A:概念:为数组开辟内存空间,为每个数组元素赋予值(内存分配问题就在下面哦)

  • B:方式:

    • a:动态初始化 → 只指定长度,由系统给出初始化值

    • b:静态初始化 → 给出初始化值,由系统决定长度

  • A:动态初始化格式:

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

Eg: int [] arr = new int [3];

  • B:静态初始化格式:

数据类型 [] 数组名 = new 数据类型 [] {元素1,元素2,…};

Eg:int [] arr = new int [] {1,2,3};

简化格式:

数据类型 [] 数组名 = {元素1,元素2,…};

Eg:int [] arr = {1,2,3};

数组的访问:

数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 数组长度-1。(这只球队可是有0号选手的哦吼~)

进阶补充知识:

在Java中,数组是一种效率最高的存储和随机访问对象的引用序列的方式。数组就是一个简单的线性序列,这使得元素访问非常快速。但是为这种速度所付出的代价是数组对象的大小被固定,并且在其生命周期中不可改变。你可能会建议使用ArrayList,它可以通过创建一个新实例,然后把旧实例中所有的引用到移到新实例中,从而实现更多空间的自动分配。尽管通常应该首选ArrayList而不是数组、但是这种弹性需要开销,因此,ArrayList的效率比数组低很多。

——Thinking in Java 第16章

❤ 3.2_1 java中的内存分配

Java为了对数据进行空间分配而划分的5个内存空间

栈区(stack area) 函数中定义的基本类型变量,对象的引用变量(对象在堆上的地址)都在函数的栈内存中分配。
栈内存特点,数数据一执行完毕,变量会立即释放,节约内存空间。
栈内存中的数据,没有默认初始化值,需要手动设置。
堆区(heap area) 堆内存用来存放new创建的对象和数组。
堆内存中所有的实体都有内存地址值。
堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。
堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也是JAVA优于C++的表现之一(C++中需要程序员手动清除)。
方法区(**Method Area**) 存储所有类(class)和静态变量(static)
本地方法区 (**Native Method Area**) 后期补充
寄存器 后期补充

❤ 3.2_2常见数组练习

(一) 遍历数组

理解:简单来说就是把数组中的每一个元素都读一遍**,你可以对数组中的每一个数进行处理,又或者找到数组中那个你需要的数。

但是有时候就想鸭,每一次我的数组元素数量较少的时候还可以,我数一数有多少个元素也就知道我需要遍历多少次了,但是如果数组元素太多呢,又或者我把遍历数组编写成一个方法,参数就是一个数组,不同的数组(元素数量不同),很显然需要遍历的次数是不灵活的,所以我们介绍一个更为灵活的属性——length

针对元素数量较多的数组 可以使用 length属性 获取数组的长度

(二) 获取数组中的最小值或最大值

思路:

从数组中任意找一个元素作为参照物

然后遍历其他的元素

一次获取和参照物进行比较,如果大就留下来,如果小就离开

(三) 数组逆序

❤ 3.2_3 For-Each 循环

JDK 1.5 引进了一种新的循环类型,被称为 For-Each 循环或者增强For循环, 它能在不使用下标的情况下遍历数组。

格式:

它的功能强大就在于不必为了下标的起始值和终止值而分心,代码更加简洁,更不容易出错。

事物总是有两面性的,虽然增强for循环带来了简洁和快速,但是并不是万能的,有的时候我们必须使用传统的for循环,例如不希望遍历每一个元素,或者在循环内部需要使用下标等。

补充:

如果仅仅是想要打印数组中的所有值,我们可以利用Arrays类中的toString方法

输出后格式如下:“[1,3,6,5,6]”

❤ 3.2_4排序方法

贫穷使我面目全非……〒_〒

假如我想在某宝买一本五年高考,三年模拟(搞笑脸),又担心买到的不是正版印刷(再次搞笑),我们可以选择销量优先展示商品,而我们又嫌贵又渴望知识的时候(哈哈哈~),我们又可以选择价格从低到高排序展示商品。

那么,网站是如何做到快速将商品按照某种规则排序的呢?

下面我们就来介绍几种常见的排序方法

数组是用来存储一些数据的“容器”,可能我们需要将其中的元素,按照我们一定的规则进行处理,使其成为有序的序列。


(一) 冒泡排序

我们先通过一个直观的例子来看一这种排序方法是如何操作的呢

要排序的数组 int[] = {3, 9, 6, 5};

第一趟排序:

第一次排序:3和9比较,3小于9,不交换位置:3 9 6 5

第二次排序:9和6比较,9大于6,交换位置:3 6 9 5

第二次排序:9和5比较,9大于5,交换位置:3 6 5 9

————————————————————————————

第二趟排序:

第一次排序:3和6比较,3小于6,不交换位置:3 6 5 9

第二次排序:6和5比较,6大于5,交换位置:3 5 6 9

————————————————————————————

第三趟排序:

第一次排序:3和5比较,3小于5,不交换位置:3 5 6 9

根据上例的规律,我们得到了冒泡排序的原理:

重复地走访要排列的元素列,一次比较两个相邻的元素,如果它们的顺序错误则交换

走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序 完成。


为了理解这个看起来很复杂的定义,我们来梳理一下上面的例子:

第一趟:经过三次排序,得到结果:3 6 5 9

第二趟:经过两次排序,得到结果:3 5 6 9

第三趟:经过一次排序,得到结果:3 6 5 9

(第三趟也是存在的只不过是,在第二趟的时候结果已经符合规定)

我们通过梳理可以看到

我们在第一趟中,4个数字,经历了3次排序,确定了最大值

在第二趟中,3个数字(最后一位已经确定,所以不计),经历了2次排序,确定了最大值

在第三趟中,2个数字(倒数两位已经确定,所以不计),经历了1次排序,确定了最大值

慢慢的最大值或者最小值(根据排序规则)会像气泡一样浮到数列的顶端,故得名冒泡排序


思路

  • 外层循环:控制它要走几次
    假设你有5个数,那就要走4次,最后一次不用走,最后那个数已 经在它位置了所以就要length-1次

  • 内层循环:控制逐一比较,如果发现前一个数比后一个数大,则交换
    注意!因为越比较长度就越小了,所以长度要length-1-i

    所以:n个元素进行排序,我们需要进行n-1 趟,每一趟循环 lenght-1-i次

Ps:length-1代表最后一项,数组下标从0开始

冒泡排序只是我们众多排序中的一种比较简单的方法(效率不是很高,但入门必须学习)

其他的排序方法,我们放到板块数据结构与算法中详细讲解

要想对数值型数组进行排序,可以使用Array类中的sort方法

格式:int[] arr = new int [520];

……..

Array.sort(arr)

sort方法本质是快速排序算法(高效快速)

❤ 3.2_5二维数组

具有两个下标的数组称为二维数组。有些数据要依赖于两个因素才能惟一地确定

例如我们下面的这个案例一个班级有三个学生,每个学生又对应四科成绩,所以我们必须用一个二维数组来存储,第一项储存学生信息,第二项存储成绩信息

Student Number Course1 Course2 Course3 Course4
Student1 55 66 58 77
Student2 87 58 48 64
Student3 65 78 70 56

Java中,二维数组中元素排列的顺序是:

定义格式:

A:

B:

从最高维开始,分别为每一维分配空间

如果想要在定义的时候就直接赋值,格式见例题中的示例

❤ 3.26 常见二维数组练习

(一)遍历二维数组

(一) 普通for循环版

(二) 增强for循环版

(三) Arrays类中的deepToString()方法

这个方法可以快速 打印一个二维数组的数据元素列表

(二)输出杨辉三角

3.3补充问题

❤ 3.3_1参数传递问题

开局一张图,内容全靠编~

有了前面知识的一些铺垫,我们终于可以引出这个问题了,诺,下面题目中利用方法重载给出了两个不同参数的change方法,分别在主函数中输出调用方法前和后的数据,看一看输出的数据和我们所想的一样吗?

小白:变量a和b在change方法中已经被重新赋值了,第二局输出那必然是 a=20, b=40

大佬:错!错!错!正确结果为输出 a=10, b=20

小白:虽然我也不太明白,但是有了第一个的经验,那我第二个我还不会吗,arr[1] 当然是2了

大佬:em……答案是4…….

(绝望脸…)

然后我们通过一张图来分析一下这个问题

解释:

当基本类型作为形式参数的时候,实际参数(也就是主方法中的10和20)的值传到了 这个方法中,无论其如何操作运算,均只是对被传入的值进行操作,方法结束后即消失, 不会对实际参数有任何的影响

当引用类型作为形式参数的时候实际参数和形式参数均指向了同一个地址,所以形式 参数的改变会直接影响到实际参数

总结:

基本类型:形式参数的改变对实际参数没有影响

引用类型:形式参数的改变直接影响实际参数

❤ 3.3_2 加密问题(作为练习)

加密规则: 将数据倒序,然后将每位数字都加上5,再用和除以10的余数 代替该数字,最后将第一位和最后一位数字交换

结尾:

如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !^_^

如果能帮到你的话,那就来关注我吧!

在这里的我们素不相识,却都在为了自己的梦而努力 ❤

一个坚持推送原创Java技术的公众号:理想二旬不止


   转载规则


《004-Java方法和数组》 BWH_Steven 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录