方法和数组
1. 方法概述
什么是方法?
方法,也叫函数,是完成特定功能的代码块。简单来说,一个方法就是一个功能、一个动作或一种行为。
为什么需要方法?
当一些代码被反复使用时,可以把它们提取出来,放到一个方法里,以方法的形式来使用这些代码。
方法的好处
大大提高了代码的复用性,方便维护
2. 方法的格式
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2…){
// 方法体语句;
return 返回值;
}
方法的格式说明
- 修饰符:public static
- 返回值类型:方法执行结果的数据类型
- 方法名:方法的名称,符合标识符命名规则即可
- 参数列表:方法执行需要的条件。
参数类型:可以是基本类型,也可以是引用类型
参数名:即变量名 - 方法体语句:完成特定功能的代码
- return:意思是返回,用于结束方法
- 返回值:方法执行之后的结果,返回给方法的使用者。若方法没有返回值,则它的返回值类型为void,比如main方法
3. 方法的定义和调用
3.1 方法的定义
- 需求:求两个数的和
- 代码演示:
public class MethodDemo1 {
public static void main(String[] args) {
/*
调用方法的注意事项:
1. 可以根据方法名直接调用方法
// 通俗来讲,调用哪个方法就写该方法的名字
2. 方法要什么,你就给什么
// 方法需要什么类型的参数,你就传入什么类型的值
3. 方法返回什么,你就用什么类型的变量来接收
*/
int c = sum(3, 4);
System.out.println(c);
}
/*
注意:
方法和方法之间是平级的关系,不能嵌套定义
要定义方法,注意三个明确:
明确方法名
明确返回值的类型
明确参数列表
*/
// 需求:定义一个方法,用来获取两个整数的和
public static int sum(int a, int b) {
// 方法体语句,其实就是具体的运算过程了
int c = a + b; // c记录的就是两个整数和
return c;
}
}
- 运行结果:
3.2 方法的调用
- 概念:使用方法的过程称为方法的调用
- 调用方式
A:通过方法名调用方法
B:根据形式参数列表将实际参数传递给方法
形式参数:在定义方法时需明确方法参数的形式,比如参数的类型和个数,故方法定义时的参数列表成为形式参数
实际参数:调用方法时传递给方法的数据,必须符合形式参数的个数和对应未知的数据类型
3.3 方法调用过程图解
- 通过方法名调用方法
- 传递实际参数
- 方法执行时,实际参数值赋值给形势参数
- 在方法中进行运算,并将结果复制给变量c
- 方法的返回值c赋值给接收者x,如果方法没有返回值,则不需要接收
3.4 案例:比较两个整数是否相同
- 需求:键盘录入两个整数,比较它们是否相同
- 代码演示:
import java.util.Scanner;
public class MethodDemo2 {
public static void main(String[] args) {
// 需求:键盘录入两个数字,比较他们是否相同
// 2. 通过键盘录入功能,接收用户录入的两个整数
// 2.1 创建键盘录入对象
Scanner sc = new Scanner(System.in);
// 2.2 提示用户录入两个数字
System.out.println("请录入第一个整数:");
int num1 = sc.nextInt();
System.out.println("请录入第二个整数:");
int num2 = sc.nextInt(); // num1,num2 实参
// 3. 调用方法,获取结果,并打印
boolean c = compare(num1, num2);
System.out.println(c);
}
/*
1. 定义方法,用来判断两个整数是否相等
明确方法名: compare
明确返回值类型: boolean
明确参数列表: int a, int b
*/
public static boolean compare(int a, int b) {
// 具体比较的过程
// 原始做法
/*boolean c = (a == b);
return c;*/
return a == b;
}
}
- 运行结果:
3.5 定义方法的注意事项
1.方法必须定义在类中
2.方法之间是平级关系,不能嵌套
3.方法没有返回值时,也要有返回值类型:void
4.方法返回值类型为void时,可以省略return语句
5.return语句后的数据类型必须和返回值类型匹配
6.return之后不能再放置语句
4. 方法重载
4.1 什么是方法重载?
在同一个类中的多个方法,它们的方法名相同,参数列表不同,这样的情况,成为方法重载。方法重载与返回值类型无关。
参数列表不同:
参数的个数不同
对应未知的参数类型不同
方法签名:方法名 + 参数列表
4.2 为什么需要方法重载?
当实现的功能相同,但具体的实现方式不同时,我们可以通过定义名称相同,参数(条件)不同的方法,来更好的识别和管理类中的方法。
4.3 案例:比较两个数是否相同
- **需求:**分别比较两个int/long/double型的数是否相同
- 代码演示
public class OverLoadDemo {
public static void main(String[] args) {
// 方法重载与方法的返回值类型无关
// 需求:定义方法,分别比较两个int/long/double的数据,判断他们是否相同
// 4. 调用比较两个int类型数据的方法
int a = 10;
int b = 20;
boolean flag1 = compare(a, b);
System.out.println(flag1);
System.out.println("----------");
// 5. 调用比较两个long类型数据的方法
long num1 = 10L;
long num2 = 20L;
boolean flag2 = compare(num1, num2);
System.out.println(flag2);
System.out.println("----------");
// 6. 调用比较两个double类型数据的方法
double d1 = 2.3;
double d2 = 2.4;
boolean flag3 = compare(d1, d2);
System.out.println(flag3);
}
// 1. 定义方法,比较两个int类型的数据是否相同
public static boolean compare(int a, int b) {
System.out.println("判断两个int类型的数据是否相同");
return a == b;
}
// 1. 定义方法,比较两个long类型的数据是否相同
public static boolean compare(long a, long b) {
System.out.println("判断两个long类型的数据是否相同");
return a == b;
}
// 1. 定义方法,比较两个double类型的数据是否相同
public static boolean compare(double a, double b) {
System.out.println("判断两个int类型的数据是否相同");
return a == b;
}
}
- 运行结果
5. 数组概述
5.1 为什么需要数组?
为了存储多个数据值
5.2 什么是数组
数组是用来存储同一种数据类型多个元素的容器。
数据类型:可以是基本类型,也可以是引用类型
容器:比如教室、衣柜、纸箱等,可以存放多个事物
5.3 数组的定义格式
5.3.1 数组的定义格式一
数据类型[ ] 数组名 = new 数据类型[长度];}
定义格式详解
数据类型:即数组中存储元素的数据类型,可以是基本数据类型,也可以是引用数据类型
[ ]:表示数组
数组名:数组的变量名,遵循标识符命名规范
new:创建数组的关键字,通过new开辟 内存空间
长度:即数组长度,数组最多能够存放元素的个数。
数组长度在定义时,不可更改
5.3.2 数组的定义格式二
数据类型[ ] 数组名 = new 数据类型[ ]{ 元素1,元素2,元素3…};
格式二的好处:定义时元素是确定的,避免内存空间的浪费
5.3.3 数组的定义格式三
数据类型[ ] 数组名= {元素1,元素2,元素3…};
格式三是格式二的变形,简化了代码编写
5.3.4 案例:定义数组
- 代码演示
public class ArrayDemo1 {
public static void main(String[] args) {
// 需求:定义一个长度为3的int类型的数组
// 格式1:虽然定义好了,但是具体存储哪三个数字,不确定
int[] arr1 = new int[3];
// 格式2:
int[] arr2 = new int[]{1, 2, 3};
// 格式3:
int[] arr3 = {1, 2, 3};
}
}
6. 数组的定义和访问
6.1 数组的访问
通过数组的索引访问数组的元素
索引: 也叫下标、脚标,是数组元素距离数组起始位置的偏移量
第一个元素的偏移量为0,所以数组的索引从0开始
格式: 数组名[索引]
取值:数组名[索引]
赋值:数组名[索引] = 值;
案例1:
- 代码演示
public class ArrayDemo2 {
public static void main(String[] args) {
// 需求:打印数组中指定元素
// 1. 定义一个数组
int[] arr = {11, 22, 33};
// 需求:输出第三个元素的值(它的索引是2)
System.out.println(arr[2]);
// 需求:将数组第一个元素的值改为10
arr[0] = 10;
System.out.println(arr[0]);
}
}
- 运行结果
案例2:数组的遍历
- 需求:给定一个Int型数组,输出数组中的每一个元素
- 分析:
- A:使用格式一定义一个长度为5的int型数组
- B:为数组的前三个元素分别赋值为1,2,3
- C:使用循环遍历数组
数组的长度:数组名.length - 结论
- 数组的最大索引为数组长度 - 1
- 数组中未手动赋值的元素,有默认值0
- 直接输出数组变量名,得到的是数组的内存地址值
- 代码演示
public class ArrayDemo3 {
public static void main(String[] args) {
// 需求:定义一个长度为5的int型数组,将前三个元素分别赋值为1,2,3,通过for循环遍历数组,打印数组中每个元素的值
/*
1.直接输出数组变量名,得到的是数组的内存地址值
2. 数组中未手动赋值的元素,其实是有默认值的,例如:int型数组默认值是0,double型数组默认值是0.0
3.数组的长度:数组名.length
数组的最大索引:数组的长度 - 1
*/
// 1. 定义一个长度为5的int型数组
int[] arr = new int[5];
// 2. 将前三个元素分别赋值为1,2,3
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
// 传统做法:遍历数组
// System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
System.out.println("arr数组的长度是" + arr.length);
System.out.println("arr数组的最大索引是:" + (arr.length - 1));
System.out.println("--------------");
// 3. 通过for循环遍历数组,打印数组中每个元素的值
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
- 运行结果
6.2 数组的初始化
在内存中为数组开辟连续空间并为每个元素赋值的过程
内存: 计算机的重要组件,用于程序运行中临时存储数据
连续空间: 数组元素在内存空间中的存放位置是连续的
动态初始化:只指定长度,由系统给出默认值
整数型:0
浮点型:0.0
字符型:‘\u0000’(空字符)
布尔型:false
引用类型:null
动态初始化:给出初始化值,由系统决定数组长度
6.2.1 Java程序的内存分配
方法区:存储可运行的class文件,包含方法,静态成员,常量等(面向对象部分详解)
栈:方法运行时使用的内存,特点是“后进先出”,即最先进入栈区的方法最后出栈,比如main方法
堆:存储new出来的数组或对象(面向对象部分详解)
本地方法栈:JVM在调用操作系统功能时使用,与开发无关
寄存器:CPU使用,与开发无关
数组类型:变量arr存储的数组在堆内存中的地址值,而不是数组元素的值,变量arr通过内存地址引起用堆内存中的数组,所以数组是引用类型。
6.2.2 数组初始化过程图
动态初始化图解
静态初始化图解
两个数组的内存图解
一个数组两个引用的内存图解
- 代码演示
public class ArrayDemo4 {
public static void main(String[] args) {
// 需求:一个数组两个引用的内存图解
// 定义arr1数组
int[] arr1 = new int[3];
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
System.out.println("-----------------");
// 定义arr2数组
int[] arr2 = arr1; // 意思是说:数组arr2和数组arr1共享同一份堆内存空间(大白话解释:操作的是同一个数组)
arr2[2] = 33;
System.out.println(arr1[2]);
System.out.println(arr2[2]);
}
}
- 运行结果
6.2.3 数组使用中两个常见问题
- 数组索引越界异常:ArrayIndexOutOfBoundsException
- 代码演示:
public class ArrayDemo5 {
public static void main(String[] args) {
// 需求:演示数组索引越界异常(ArrayIndexOutOfBoundException)
int[] arr = new int[3];
arr[0] = 11;
arr[1] = 22;
arr[2] = 33;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}
}
-
运行结果:
-
图解
- 空指针异常:NullPointerException
数组引用存储的值为null而非数组的地址值时
- 代码演示
public class ArrayDemo6 {
public static void main(String[] args) {
// 需求:演示空指针异常(NullPointerException)
int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr = null;
System.out.println(arr[0]);
}
}
-
运行结果
-
-
图解
7. 数组的常见操作
案例1:
- 代码演示
public class ArrayDemo7 {
public static void main(String[] args) {
// 需求:给定一个int类型数组,找出它的最大元素
// 1. 定义int[]
int[] arr = {1, 2, 3, 4, 5, 6};
// 2. 定义一个临时变量temp,用来表示最大值
int temp = arr[0];
// 3. 通过for循环遍历数组,获取到每一个数据
for (int i = 0; i < arr.length; i++) {
// arr[i] 表示的就是数组中的每一个数据。
// 4. 把获取到的数据依次和temp进行比较,并将较大的值赋值给temp.
if (arr[i] > temp) {
temp = arr[i];
}
}
// 5. for循环执行结束后,temp记录的就是最大值,打印即可
System.out.println("数组中最大元素为:" + temp);
}
}
- 运行结果
案例2:定义打印数组元素的方法并调用过程图解
- 代码演示
public class ArrayDemo8 {
public static void main(String[] args) {
// 需求:定义一个方法用来打印数组,并调用
// 1. 定义一个数组
int[] arr = {2, 3, 5, 9, 6, 7};
// 3. 调用方法
printArray(arr);
}
/*
// 2.定义一个方法,是用来打印数组的
明确方法名: printArray
明确参数列表: int[] arr
明确返回值的类型: void
*/
public static void printArray(int[] array) {
// 这里边写的是具体的遍历数组的代码
for (int i = 0; i < array.length; i++) {
// i的最大值为arr.length - 1,相当于数组的最大索引
System.out.println(array[i]);
}
}
}
- 运行结果
- 过程图解
案例3:
- 代码演示
public class ArrayDemo9 {
public static void main(String[] args) {
/*
结论:
1. 基本类型的变量作为参数传递时,传递的是值
2. 引用类型的变量作为参数传递时,传递的是地址值
*/
int x = 3;
int y = 4;
int z = sum(x, y);
System.out.println(x);
System.out.println(y);
System.out.println(z);
}
public static int sum(int a, int b) {
int c = a + b;
a++;
b++;
return c;
}
}
- 运行结果
注意:引用类型的变量作为参数传递给方法时,传递的是地址值