6.方法
本章目标
- 方法概念
- 自定义方法
- 参数传递
- 贯穿案例
本章内容
我们使用String中的length()方法来求字符串的长度,通过println()来打印出内容,那么如果我们想有个方法来求两数之和,还有方法来实现登录功能,这时该怎么办?这时就要使用到自定义方法了
如何实现一个类似于Windows计算器的功能呢?
一、方法概念
1、什么是方法
方法是个黑匣子
,是一段用来完成特定功能的代码片段,是程序中最小的执行单元。
在一个程序中,相同的程序段可能会多次重复出现,为了减少代码量和出错概率,一般将这些重复出现的代码段单独抽出来,写成子程序形式,以供多次调用。
这类子程序在Java语言中叫做方法
这类子程序也叫
函数
(如C语言)
2、方法的好处
方法是Java语言的重要概念之一,同时也是实现结构化程序设计的主要手段,结构化程序设计是面向对象程序设计的基础,因此,掌握Java方法非常重要。 常见好处下如:
- 提高代码的复用性
- 提高程序的可维护性
- 分而治之
3、方法分类
java中方法可以分为两大类:
3.1、库方法
- main()方法
- System.out.println()
- 各种系统工具类提供的方法
3.2、自定义方法
除了系统提供的方法之外,往往我们还需要开发大量自己的方法来使用,比如要求两个年龄的平均值,我们可以定义一个方法如下:
public static int avgAge(int x, int y){
int result;
result = (x + y) / 2;
return result;
}
二、自定义方法
1、语法格式
修饰符 返回值类型 方法名 (参数类型 参数名,……){
...
方法体
...
return 返回值;
}
图解:
2、方法说明
方法包含一个方法头和一个方法体,具体信息如下:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法,定义了该方法的访问类型。
- 返回值类型 :方法可能会返回值。
returnValueType
是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType
是关键字void
。 - 方法名:是方法的实际名称,驼峰式命名法,一般第一单词是动词,后面跟名词
- 方法签名参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 方法体:方法体包含具体的语句,定义该方法的功能
3、方法的分类
从方法和过程两种功能这一角度
- 有返回值方法
- 无返回值方法
从主调方法和被调方法之间数据传递的角度
- 无参方法
- 有参方法
4、方法的调用
注:此处我们暂不考虑实例方法,只考虑static修饰的静态方法
在程序中是通过对方法的调用来执行方法体的,Java语言中,静态方法调用的一般形式为:
- 在类的内部调用时,直接通过
方法名(参数列表)
调用 - 调用其他类的静态方法时,通过
类.方法名(参数列表)
调用
对无参方法调用时则只要写上小括号即可。实际参数表中的参数可以是常数,变量或其它构造类型数据及表达式,各实参之间要用逗号间隔开,并注意需与形参相对应。
5、无参无返回
不带参数同时也没有返回值的方法示例
/**
* 有参无返回类型
*
*/
public static void printTriangle() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
-
调用
public static void main(String[] args) {
System.out.println(“打印一个五行一列的直接三角形”);
printTriangle();
}
5、有参无返回
根据用户输入的行数,来打印出对应的行数的三角型来
/**
* 有参无返回类型
* @param 面积
*/
public static void printTriangle(int row) {
for (int i = 0; i < row; i++) {
for (int j = 0; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
-
调用
public static void main(String[] args) { System.out.println(“请输入要打印直接三角形行数”); Scanner scanner = new Scanner(System.in); int row = scanner.nextInt(); scanner.close(); printTriangle(row); }
6、有返回无参
这种情况应该很少,调用某个方法得到一个固定的数值
/**
* 根固定的圆的半径,计算出圆的面积
* @return 面积
*/
public static double getArea() {
double r = 2;
double area = 3.14 * r * r;
return area;
}
-
调用
public static void main(String[] args) { double area = getArea(); System.out.println(area); }
7、有参有返回
最为常用,各种应用场景,
/**
* 根据输入的圆的半径,计算出圆的面积
* @param radius 半径
* @return 面积
*/
public static double getArea(double radius) {
double area = 3.14 * radius * radius;
return area;
}
-
调用
public static void main(String[] args) { System.out.println("请输入圆的半径,我给你得到面积"); Scanner scanner = new Scanner(System.in); double r = scanner.nextDouble(); scanner.close(); double area = getArea(r); System.out.println("半径为"+r+"的圆的面积为:"+area);
}
8、实现计算器功能
/**
*
* @param a 第一个参数
* @param b 第二参数
* @return 两个数的和
*/
public static int sum(int a, int b) {
int result = a + b;
return result;
}
public static int counter(int a, int b, String oper) {
int result = 0;
switch (oper) {
case "+":
result = a + b;
break;
case "-":
result = a - b;
break;
case "*":
result = a * b;
break;
case "/":
result = a / b;
break;
case "%":
result = a % b;
break;
default:
break;
}
return result;
}
9、方法嵌套调用
Java语言允许在一个方法的定义中出现对另一个方法的调用,我们把这样的情况称为方法的嵌套(调用),即在被调方法中又调用了其它方法
需要:定义一个求圆柱体体积的方法,要求利用求圆面积的方法来实现,并在main()方法中进行验证
/**
* 根据输入的圆的半径,计算出圆的面积
*
* @param radius 半径
* @return 面积
*/
public static double getArea(double radius) {
double area = 3.14 * radius * radius;
return area;
}
/**
*
* @param height 高
* @param radius 半径
* @return 圆体积
*/
public static double getVolume(double height, double radius) {
//调用上面求圆面积的方法
double volume = getArea(radius) * height;
return volume;
}
-
调用
public static void main(String[] args) { System.out.println("1、请输入圆柱底的半径"); Scanner scanner = new Scanner(System.in); double r = scanner.nextDouble(); System.out.println("2、请输入圆柱的高"); int h = scanner.nextInt(); scanner.close(); double v = getVolume(h, r); System.out.println("底面半径为" + r + ",高度为" + h + "的圆柱体体积:" + v); }
三、参数传递
1、什么是参数传递
方法的定义是在类的设计中进行的,方法的使用是在实际运行中进行的,定义方法的时候使用形式参数(形参),而调用方法时候,用实际参数(实参)取代形式参数,这个过程称为参数传递
当对带参方法进行调用时,实际参数将会传递给形式参数,也就是实参与形参结合的过程。
2、形参及实参
参数是方法调用时进行信息交换的渠道之一,方法的参数分为形参和实参两种
形参和实参的功能是作数据传送。发生方法调用时,主调方法把实参的值传送给被调方法的形参,从而实现主调方法传递数据给被调方法
2.1、形参
形参出现在方法定义中,在整个方法体内都可以使用,离开该方法则不能使用。
形参只在方法被调用时才分配内存单元,在调用结束时,便会“释放”所分配的内存单元。因此,形参只在本方法内有效,方法调用结束后就不能再使用。
方法内部定义的(局部)变量也是如此。
2.2、实参
实参出现在主调方法中,进入被调方法后,实参变量也不能使用。
实参可以是常量、变量、表达式,甚至是方法等,无论实参是何种类型的量,在进行方法调用时,它们都必须具有确定的值,以便把这些值传递给形参 实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。
方法调用中发生的数据传递是单向的,因此在方法调用过程中,若形参的值改变,则实参不会跟着改变。
3、传值
值传递就是实参将值复制给形参,系统要为形参开设存储空间,以接受传递的值,此时形参成为一个实在的局部变量
实参和形参脱离关系,形参在方法中参与运算,在运算中发生的任何变化都不会影响实参
public static void main(String[] args) {
// 定义两个实参,基本类型属于值传递
int a = 1, b = 1;
int result = sum(a, b);
System.out.println("结果:result=" + result);
System.out.println("由于是传值,所以实现a的值不会改为,a=" + a);
}
/**
* 不要被这里的名字迷惑,这两形参a,b和调用方法里实际没有关系
* @param a
* @param b
* @return
*/
public static int sum(int a, int b) {
a++;// 改为形参 a的值,加1
int result = a + b;
return result;
}
-
运行结果
结果:result=3
由于是传值,所以实现a的值不会改为,a=1
4、传引用
引用传递就是地址传递,即将实参的地址传递给形参,此时形参并不开辟单独的空间,而是指定到实参的地址,此时形参和实参共享一个地址
如果通过形参改变了空间的值那么实参也随之改变,Java中引用有:
- 数组
- 类
- 接口
这三种都属性引用类型,传的都是地址
5、数组参数
数组可以作为参数向方法传递,有两种情况:
- 向方法传递
数组元素
也就是用数组元素作为方法的实参,与其他类型的参数没有区别,对数组元素的操作不会影响到实参。 - 向方法传递
数组
也就是用数组作为方法的实参,这时要注意:在方法调用过程中,实际上传递的是指向某个数组结构的引用,在方法中对数组形参的操作会对实参产生影响。
5.1、示例一
以下例子会输出什么?
public static void main(String[] args) {
int[] array1 = new int[]{12,32,52};
int[] array2 = new int[]{26,46,66,86};
array1 = array2;
for (int i : array1) {
System.out.println(i);
}
}
-
结果
26
46
66
86
对相同数据类型的数组变量之间的相互赋值实际上是改变了变量原先保存的数组结构地址,让数组变量重新指向其他数组结构:最后使变量array1
和array2
指向同一个数组结构
5.2、示例二
数组作为参数传递
测试时可以先不改变数组中的值进行测试,然后再改变,对比运行结果
public static void main(String[] args) {
int[] array1 = new int[] { 12, 32, 52, 23, 89 };
int max = max(array1);
System.out.println("数组中最大值为:" + max);
System.out.println("运行后数组中的内容");
for (int i : array1) {
System.out.println(i);
}
}
/**
* 求数组最大值
* @param array
* @return
*/
public static int max(int[] array) {
array[0] = 100;//改变数组中的值
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
}
}
return max;
}
-
运行结果
数组中最大值为:100
运行后数组中的内容
100
32
52
23
89
5.3、示例三
数组元素作为参数传递
public static void main(String[] args) {
int[] array1 = new int[] { 12, 32, 52, 23, 89 };
int result = sum(array1[0],array1[1]);
System.out.println("求和结果为:" + result);
System.out.println("运行后数组中的内容");
for (int i : array1) {
System.out.println(i);
}
}
/**
* 不要被这里的名字迷惑,这两形参a,b和调用方法里实际没有关系
*
* @param a
* @param b
* @return
*/
public static int sum(int a, int b) {
a++;// 改为形参 a的值,加1
int result = a + b;
return result;
}
-
运行结果
求和结果为:45
运行后数组中的内容
12
32
52
23
89
虽然形参a+1了,但数组中的值并没有被改变
四、贯穿案例
1、完善HRMS系统 ,添加如下功能:按关键字模糊查询人员、按下标删除人员
2、用自定义函数封装内循环功能.
package day0823;
import java.util.Scanner;
public class HRMS {
public static void main(String[] args) {
//完善HRMS系统 ,添加如下功能:按关键字模糊查询人员、按下标删除人员
//用自定义函数封装内循环功能.
String[] employees = new String[5];//构造一个初始容量为5的数组
Scanner scanner = new Scanner(System.in);//构造一个接收键盘输入的对象
int index = 0;//代表当前数组的下标所在位置
System.out.println("欢迎进入人事管理系统!!!");
while(true) {
System.out.println("请选择操作:1、显示所有员工 2、添加员工 3、根据关键字模糊查询 4、根据索引下标删除 9、退出");
int operator = scanner.nextInt();
if(operator == 9) {
break;
}else if(operator == 1) {//显示所有员工的
eachArray(employees);//调用自定义方法,打印所有员工
}else if(operator==2) {
System.out.println("请输入员工姓名");
String empName = scanner.next();
employees[index] = empName;//得到员工姓名,并添加到数组中
index++;//指向到数组的下一个坐标
}else if(operator == 3) {
System.out.println("请输入查询关键字");
String name = scanner.next();
String[] resultArray2 = searchName(name, employees);//根据key,查询结果,并返回一个数组
eachArray(resultArray2);//调用迭代方法,显示员工信息
}else if(operator ==4) {
System.out.println("请选择要删除的员工,选择数字");
// 调用方法
eachArray(employees);
int index2 = scanner.nextInt();
if(index2>=0&&index2<employees.length) {
employees[index2] = null;
}
}
}
System.out.println("再见!!");
scanner.close();
}
/**
* 挑选满足条件的员工,并返回
* @param name
* @param arr
* @return
*/
public static String[] searchName(String name,String[] arr) {
String[] resultArray = new String[arr.length];
int index = 0;
for (int i = 0; i < arr.length; i++) {
//if条件在逻辑于的情况下,如果前面条件不成立,则不再执行后面的逻辑判断
if(arr[i]!=null&&arr[i].contains(name)) {
resultArray[index] = arr[i];
index++;
}
}
return resultArray;
}
/**
* 迭代数组
* @param arr
*/
public static void eachArray(String[] arr) {
for (int i = 0; i < arr.length; i++) {
if(arr[i]!=null) {
System.out.println("当前员工:"+arr[i]);
}
}
}
}
时间充足可扩展:可变参数
思维导图
本文来自博客园,作者:icui4cu,转载请注明原文链接:https://www.cnblogs.com/icui4cu/p/18733616