方法的概述
使用方法的优点
1.简化了代码
2.提高了代码的扩展性和可维护性
3.我们从一个方法的实现者转而成为了一个方法的调用者指挥者,这也是面向对象思想的核心基础
方法概念
完成特定功能的代码片段
数学中成为函数:
y = f(x,y)
方法的格式
访问权限修饰符 返回值类型 方法名称(参数类型 参数名1, 参数类型 参数名2, … , 参数类型 参数名n) [throws 异常类名] {
方法体; // method stub
return 返回值;
}
返回值类型: 可以是八大基本书类型也可以是引用类型,必须和return关键字后面的值的类型保持一致
当一个方法没有返回结果的时候,返回值为void
方法名称: 需见名知意,驼峰命名法,一般是动词
参数类型: 可以是八大基本书类型也可以是引用类型
参数名: 满足变量的命名规范,其实本质就是一个局部变量(这个参数变量作用在方法体中)
形式参数: 方法定义的时候的参数
实际参数: 方法调用的时候的参数
throws 异常类名
方法体: 完成特定功能的代码片段
return 返回值: 返回结果给调用者,谁调用该方法就返回给谁,必须和返回值类型保持一致
如果返回值类型是void,那么return 返回值这句话可以不写,但是可以写 return;
方法书写的位置
因为方法是平级关系,main是一个主方法,也是方法,JVM调用
和main平级,类体以内,方法体以外
方法的三要素
1.返回值类型
2.参数列表
3.方法名
方法调用的三要素
1.返回什么类型的值就拿什么类型的值接收,满足类型转换规则 (基本类型【强转和自转】还有引用类型【向上转型和向下转型】)
2.需要传什么类型的参数就传什么类型的参数,满足类型转换规则 (基本类型【强转和自转】还有引用类型【向上转型和向下转型】)
3.参数列表必须一一对应(参数的个数,参数的顺序,参数的类型)
调用的三种方式
1.直接调用: 一般针对某个方法的返回值为void的情况
2.输出调用: 一般针对后续不需要再次使用方法的结果的时候的情况
3.赋值调用: 一般针对后续还需要多次使用方法的返回值的情况
注意
1.方法不能够嵌套定义
2.方法不调用不会执行
3.一般会写好返回值返回,再来编写方法体
import org.omg.CORBA.PUBLIC_MEMBER;
public class MethodDemo01 {
public static void main(String[] args) {
// 直接调用
printNNMulTable(8);
// 输出调用
System.out.println(add(10, 20));
// 赋值调用
int sum = add(50, 30);
sum += 10;
System.out.println(sum);
byte b = 10;
short s = 20;
System.out.println(add(b, s));
double result = add(10, 20);
System.out.println(result);
}
// 计算两个数的和
/*
* 返回值类型: int
* 参数列表: int a, int b
* 方法名: getSum/ add
*/
public static int add(int a, int b) {
int sum = 0;
sum = a + b;
return sum;
}
/*
* 打印九九乘法表
* 返回值类型: void
* 参数列表: 无参
* 方法名: print99MulTable
*/
public static void printNNMulTable(int n) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "x" + i + "=" + (i*j) + "\t");
}
System.out.println();
}
}
}
案例
需求
1、求两个数之和
2、键盘录入年份判断是否是闰年
3、键盘录入数据,返回两个数中的较大值
4、判断一个数是否是素数
5、打印n行n列的*型矩形
6、打印九九乘法表
代码实现如下:
public class MethodDemo02 {
public static void main(String[] args) {
System.out.println("两个数的和: " + add(10, 20));
Scanner input = new Scanner(System.in);
System.out.print("请输入年份: ");
int year = input.nextInt();
boolean isLeapYear = isLeapYear(year);
if (isLeapYear) {
System.out.println(year + "年是闰年");
} else {
System.out.println(year + "年不是闰年");
}
System.out.println(isLeapYear(year) ? "是闰年": "不是闰年");
System.out.println("两个数中较大的值: " + getMaxValue(100, 50));
System.out.println(isPrimeNumber(9) ? "是素数": "不是素数");
printMNRectangle(2, 5);
}
// 1、求两个数之和
public static int add(int a, int b) {
return a + b;
}
// 2、键盘录入年份判断是否是闰年
/*
* 返回值类型: boolean
* 参数列表: int year
* 方法名: isLeapYear
* 闰年分为普通闰年和世纪闰年。
* 普通闰年:能被4整除但不能被100整除的年份为普通闰年。(如2004年就是闰年,1900年不是闰年);
* 世纪闰年:能被400整除的为世纪闰年。(如2000年是世纪闰年,1900年不是世纪闰年);
*/
public static boolean isLeapYear(int year) {
// if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
// return true;
// } else {
// return false;
// }
// boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)? true: false;
// return isLeapYear;
// return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) ? true: false;
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
/*
* 3、键盘录入数据,返回两个数中的较大值
* 返回值类型: int
* 参数列表: int a, int b
* 方法名: getMaxValue
*/
public static int getMaxValue(int a, int b) {
return a > b ? a : b;
}
/*
* 4、判断一个数是否是素数
* 返回值类型: boolean
* 参数列表: int primeNumber
* 方法名: isPrimeNumber
*
* 素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
* 4 除了1和4, 遍历2~3, 2 3 2能够被4整除 不是素数
* 5 除了1和5, 遍历2~4, 2 3 4都不能够被5整数,是素数
*/
public static boolean isPrimeNumber(int primeNumber) {
// 默认是素数
boolean flag = true;
if (primeNumber < 2) {
flag = false;
} else {
// 遍历2~primeNumber-1之间的每一个数
for (int i = 2; i <= primeNumber-1; i++) {
// 判断primeNumber能够对每一个因子整除
if (primeNumber % i == 0) {
flag = false;
break;
}
}
}
return flag;
}
/*
* 5、打印m行n列的*型矩形
* 返回值类型: void
* 参数列表: int row, int column
* 方法名: printMNRectangle
*/
public static void printMNRectangle(int row, int column) {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
方法重载
方法重载的引入
为什么需要方法重载?
1.针对多个方法重名但是参数不一致的情况
2.解决了方法命名问题
方法重载
发生在同一个类中,方法名称相同,参数的个数顺序类型不同构成重载
方法重载的特点
1.发生在同一个类中
2.方法名称相同
3.参数列表不同 [顺序类型个数]
个数不同构成重载
类型不同构成重载
顺序不同构成重载
4.重载也是多态的一种表现形式(会在面向对象多态讲解)
5.系统会根据参数的顺序个数类型来调用相应的重载方法
6.实参传递给形参同样满足类型转换
7.形参的名称不能构成重载
public class MethodDemo03 {
public static void main(String[] args) {
System.out.println(add(10, 20));
System.out.println(add(10, 2.5));
System.out.println(add(10, 20, (int)2.5));
}
// 计算两个数的和
// 1
public static int add(int a, int b) {
return a + b;
}
// 2
public static int add(int c, int d, int e) {
return c + d + c;
}
// 3
public static double add(int a, double b) {
return a + b;
}
// 4
public static double add(double a, int b) {
return a + b;
}
}
方法的递归
递归: 递归是一种算法
方法递归的引用
为什么需要递归?
1.主要适用于层级不确定的情况 例如 文件递归 层级菜单…
2.主要适用于某些针对自身回路的情况
递归的特点
1.方法中调用本方法,自己调用自己
2.StackOverflowError 栈内存溢出
3.递归必须要有出口,如果没有出口,层级很深的情况,容易出现死递归
4.构造方法不能够递归
经典面试题:
死递归和死循环的区别?
死循环没有出口,死递归必须要有出口
大部分场景都是使用循环,偶尔可以巧用递归来解决一些难题
public class MethodDemo04 {
public static void main(String[] args) {
tellStory(10);
// while (true) {
// System.out.println("从前有座山,山里有座庙,庙里有个老和尚和小和尚讲故事,故事是:");
// }
}
public static void tellStory(int i) {
if (i == 0) {
return;
}
System.out.println("从前有座山,山里有座庙,庙里有个老和尚和小和尚讲故事,故事是:" + i);
tellStory(--i);
}
}
递归案例1
/*
* 递归求5的阶乘
*
*
*/
public class MethodDemo05 {
public static void main(String[] args) {
System.out.println("5的阶乘是:" + getJieChengByLoop(5));
}
public static long getJieChengByLoop(int num) {
long jc = 1L;
for (int i = 1; i <= num; i++) {
jc *= i;
}
return jc;
}
// 5 x 4 x 3 x 2 x 1
/* num * getJieChengByDigui(-- num);
* num = 5
* 120
* return 5 * 24
* return 4 * 6;
* return 3 * 2;
* return 2 * 1;
*
*/
public static long getJieChengByDigui(int num) {
if (num < 0) {
return 0;
}
// 先确定出口
if (num == 1) {
return 1;
} else {
return num * getJieChengByDigui(-- num);
}
}
}
递归案例2
/*
* 递归实现 斐波那契数列
*
* 1 1 2 3 5 8 13
*/
public class MethodDemo06 {
public static void main(String[] args) {
System.out.println(f(5));
}
/*
* n = 1
* f(1) = 1
* n = 2
* f(2) = 1
*
* n = 3
* return f(2) + f(1);
* 1 + 1
*
* n = 4
* return f(3) + f(2);
* return f(2) + f(1); + 1
* 1 + 1
*
*/
public static int f(int n) {
// 先确定出口
if (n == 1 || n == 2) {
return 1;
}
return f(n -1) + f(n - 2);
}
}
方法的调用过程