静态方法及方法的重载和递归调用
一、静态方法
1.含义:特定功能的代码块
2.优点
1.解决了代码的冗余
2.提高了代码的可读性
3.语法结构
public static 返回值类型 方法名(参数列表){
...代码块...
}
4.按照参数+返回值来分类
1.无参数无返回值的方法
2.有参数的方法
3.有返回值的方法
1.无参数无返回值的方法
语法结构:
public static void 方法名(){
...代码块...
}
需求1:设置一个方法 - method,打印5遍"用真心待人"
需求2:模拟LOL,设计走位(run)和发技能(play)的方法
需求3:设计一个方法 - printStar,打印三角形
需求4:设计三个方法(a,b,c) ,在a方法中调用b,在b方法中调用c
public class 文件名{
public static void main(String[] args){
//调用方法方式1 -- (方法之间都是在一个类里)
//method();
//调用方法方式2-- (方法之间都是在一个类里 或 不在一个类 ,就用类名调用)
//文件名.method();
//需求2:-----------------------------------------
//run();
//run();
//play();
//run();
//需求3:------------------------------------------
//printStar();
//需求4:-----------------------------------------
a();
}
public static void a(){
System.out.println("a方法被调用了");
b();
}
public static void b(){
System.out.println("b方法被调用了");
c();
}
public static void c(){
System.out.println("c方法被调用了");
}
public static void printStar(){
for(int i = 0;i<5;i++){
for(int j = 0;j<=i;j++){
System.out.print("*");
}
System.out.println();
}
}
public static void run(){
System.out.println("风骚的走位 -- 500行");
}
public static void play(){
System.out.println("发技能 -- 2000行");
}
public static void method(){
for(int i = 0;i<5;i++){
System.out.println("用真心待人");
}
}
}
注意
1.方法写在类里面
2.方法与方法之间是平级关系
3.方法如果不被调用,就是个摆设
2.有参数的方法
语法结构:
public static void 方法名(参数列表){
...代码块...
}
需求1:设计一个方法 - printStar,打印三角形,三角形的行数由调用方指定
需求升级:三角形的行数、符号由调用方指定
需求2:设计一个方法 - getMax,传入两个int类型的参数,比较最大值
public class 文件名{
public static void main(String[] args){
//需求1:--------------------------------------
//printStar(3,"*");//3,"*" - 实参
//printStar(5,"$");//5,"$" - 实参
//需求2:--------------------------------------
getMax(10,20);
}
public static void getMax(int a,int b){
int max = (a>b)?a:b;
System.out.println("最大值为:" + max);
}
public static void printStar(int num,String str){
//int num,String str - 形参
for(int i = 0;i<num;i++){
for(int j = 0;j<=i;j++){
System.out.print(str);
}
System.out.println();
}
}
}
注意
1.方法声明时,规定参数,这个参数叫做形式参数/形参
2.形参必须规定类型
3.形参也属于变量,作用域在方法内,形参也可以叫做局部变量(局部变量-方法内的变量)
4.调用方法时,传入的参数,这个参数叫做实际参数/实参
5.实参类型必须和形参类型兼容
6.多个形参或实参之间使用逗号分隔
3.有返回值的方法
语法结构:
public static 返回值类型 方法名([参数列表]){
...代码块...
return 数据;
需求:设置一个方法 - getMax,传入两个int类型的参数,比较最大值并返回
public class 文件名{
public static void main(String[] args){
//需求:比较四个int值
int num1 = 34;
int num2 = 78;
int num3 = 27;
int num4 = 55;
int max = getMax(num1,num2);
max = getMax(max,num3);
max = getMax(max,num4);
System.out.println("最大值为:" + max);
}
public static int getMax(int a,int b){
int max = (a>b)?a:b;
return max;//1.结束当前方法 2.把max返回给调用方
}
}
注意
1.void表示无返回值,说明该方法执行完毕后不需要返回任何数据
2.带有返回值的方法中根据需求可以设置参数列表或者不设置
3.参数列表表示调用该方法需要传入的数据,返回值表示方法执行完毕需要传出去的数据,参数列表和返回值不冲突
4.return 数据;表示该方法要返回的具体数据
5.方法功能的单一性,一个方法里的功能竟可能单一
6.return返回数据的类型必须和方法声明时规定的返回值类型兼容
二、方法的重载
1.含义:方法与方法之间的关系
2.优点
调用方法时,系统会根据实参类型自动匹配到具体的方法上
3.条件
1.在同一个类中
2.方法名必须一致
3.参数列表的个数或类型不一致
4.与返回值无关(方法有没有返回值跟重载是不是没有关系)
4.应用场景
当多个方法的大体功能一致(说明方法名可以一样),就考虑使用重载
需求:设计一个方法 - getMax,输入两个int值,返回最大值
需求:设计一个方法 - getMax,输入三个int值,返回最大值
需求:设计一个方法 - getMax,输入两个double值,返回最大值
需求:设计一个方法 - getMax,输入三个double值,返回最大值
public class 文件名{
public static void main(String[] args){
//细节:方法有返回值,可以直接打印(打印的就是方法的返回值)
System.out.println(getMax(10,40,30.3));
}
public static int getMax(int a,int b){
return (a>b)?a:b;
}
public static int getMax(int a,int b,int c){
int max = getMax(a,b);
max = getMax(max,c);
return max;
}
public static double getMax(double a,double b){
return (a>b)?a:b;
}
public static double getMax(double a,double b,double c){
double max = getMax(a,b);
max = getMax(max,c);
return max;
}
//注意: 两个method01()之间的关系是重载
public static void method01(String str,int i){}
public static void method01(int i,String str){}
//注意:重载只看个数或类型,不要参数名,以下代码会报错(重复定义方法)
//public static void method02(String s,int i){}
//public static void method02(String str,int ii){}
}
三、方法的递归
1.含义:方法自己调用自己
2.注意
1.找规律 2.找出口
public class 文件名{
public static void main(String[] args){
method();
}
//错误示范:StackOverflowError - 栈内存溢出的错误
//出现原因:调用方法就会在栈内存中开辟空间,用于存放方法中的局部变量。死循环的调用方法,栈内存就会满载并溢出
public static void method(){
method();
}
}
需求:设计一个方法,传入int类型的数值 - n,计算n的阶乘
5! = 1*2*3*4*5 -> 5! = 4! * 5
4! = 1*2*3*4 -> 4! = 3! * 4
3! = 1*2*3 -> 3! = 2! * 3
2! = 1*2 -> 2! = 1! * 2
1! = 1 -> 1! = 1
找规律:n! = (n-1)!*n
找出口:1! = 1
public class 文件名{
public static void main(String[] args){
int factorial = getFactorial(5);
System.out.println(factorial);//120
}
public static int getFactorial(int n){
if(n != 1){
return getFactorial(n-1)*n;
}else{
return 1;
}
}
}
需求:不死神兔 - 假设有一对兔子,从第三个月开始每个月都可以生一对兔子,
小兔子三个月开始又可以每个月生一对兔子,假设兔子不死,设计一个方 法传入月数,返回当月兔子的对数
考点:斐波那契数/黄金分割
找规律:当月兔子的对数 = 上个月 + 上上个月
找出口:第1个月和第二个月都是1对兔子
public class 文件名{
public static void main(String[] args){
int rabbit = getRabbit(9);
System.out.println(rabbit);
}
public static int getRabbit(int month){
if(month == 1 || month == 2){
return 1;
}else{
return getRabbit(month-1) + getRabbit(month-2);
}
}
}
四、方法版本的万年历
import java.util.Scanner;
public class 文件名{
/**
总结:
1.先看main方法中的流程(大体看一看)
2.再按照main方法中调用其他方法的顺序看细节代码
*/
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println("请输入年份:");
int year = scan.nextInt();
System.out.println("请输入月份:");
int month = scan.nextInt();
//获取总天数
int allDay = getAllDay(year,month);
//获取星期
int week = getWeek(allDay);
//获取当月天数
int day = getDay(year,month);
//打印日期
printCalendar(year,month,day,week);
}
//打印日历
public static void printCalendar(int year,int month,int day,int week){
System.out.println("---" + year + "年" + month + "月---");
System.out.println("一\t二\t三\t四\t五\t六\t日");
// --- 打印空格 ---
int num = 0;//控制换行
for(int i = 1;i<week;i++){
System.out.print("\t");
num++;
}
// --- 打印日期 ---
for(int i = 1;i<=day;i++){
System.out.print(i + "\t");
num++;
if(num % 7 == 0){
System.out.println();//换行
}
}
}
//获取总天数
public static int getAllDay(int year,int month){
return getAllDayOfYear(1900,year) + getAllDayOfMonth(year,1,month) + 1;
}
//获取总天数 -- 年
public static int getAllDayOfYear(int startYear,int endYear){
int allDayOfYear = 0;
for(int i = startYear;i<endYear;i++){
if(isLeapYear(i)){
allDayOfYear += 366;
}else{
allDayOfYear += 365;
}
}
return allDayOfYear;
}
//获取总天数 -- 月
public static int getAllDayOfMonth(int year,int startMonth,int endMonth){
int allDayOfMonth = 0;
for(int i = startMonth;i<endMonth;i++){
allDayOfMonth += getDay(year,i);
}
return allDayOfMonth;
}
//判断是否是闰年的方法
public static boolean isLeapYear(int year){
if((year%4==0 && year%100!=0) || (year%400==0)){
return true;
}
return false;
}
//获取当月的天数
public static int getDay(int year,int month){
int day = 0;
switch(month){
case 1:case 3:case 5:case 7:case 8:case 10:case 12:
day = 31;
break;
case 4:case 6:case 9:case 11:
day = 30;
break;
case 2:
if(isLeapYear(year)){//闰年
day = 29;
}else{//平年
day = 28;
}
break;
}
return day;
}
//获取星期
public static int getWeek(int allDay){
int week = allDay % 7;
if(week == 0){
week = 7;
}
return week;
}
}