0
点赞
收藏
分享

微信扫一扫

[java基础-4] 循环&方法:方法声明.重载.递归

程序员伟杰 2022-02-01 阅读 75

循环

死循环

  • for死循环:执行效率优先于while
for (;;) {
  循环体语句;
}
  • while死循环:代码阅读性更强
while (true) {
循环体语句;
}

循环嵌套

  • 百钱买百鸡:

    花100文钱买100只鸡,公鸡5文1只,母鸡3文1只,小鸡1文3只,花100文钱正好买100只鸡

public class BasicDemo03 {
	public static void main (String[] args) {
		/*
		循环次数=101*101*101=1030301
		for (int gong = 0; gong <= 100 ; gong++ ) {
			for (int mu = 0; mu <= 100; mu++) {
				for (int xiao = 0; xiao <= 100 ; xiao++ ) {
					if ((gong + mu + xiao == 100) && (gong * 5 + mu * 3 + xiao / 3 == 100) && (xiao % 3 == 0)) {
						System.out.println("公鸡有"+gong+"只,母鸡有"+mu+"只,小鸡有"+xiao+"只");
					}
				}
			}
		}
		*/

		/*
		//循环次数=21*34*101=72114
		for (int gong = 0; gong <= 20 ; gong++ ) {
			for (int mu = 0; mu <= 33; mu++) {
				for (int xiao = 0; xiao <= 100 ; xiao++ ) {
					if ((gong + mu + xiao == 100) && (gong * 5 + mu * 3 + xiao / 3 == 100) && (xiao % 3 == 0)) {
						System.out.println("公鸡有"+gong+"只,母鸡有"+mu+"只,小鸡有"+xiao+"只");
					}
				}
			}
		}
		*/
		//循环次数=21*34=714
		for (int gong = 0; gong <= 20 ; gong++ ) {
			for (int mu = 0; mu <= 33; mu++) {
				int xiao = 100 - gong - mu;//前提是被3整除
				if ((gong * 5 + mu * 3 + xiao / 3 == 100) && (xiao % 3 == 0)) {
					System.out.println("公鸡有"+gong+"只,母鸡有"+mu+"只,小鸡有"+xiao+"只");
				}
			}
		}
	}
}

  • 打印1-100之间所有质数:
/*
	练习:打印1-100之间所有质数
	质数:只能被1或者其本身进行整除的数,1不是质数
		特点:因数有2个
	被除数 / 除数 = 商 ...... 余数
	执行过程
		1 / 1 = 1 ...... 0
		2 / 1 = 2 ...... 0
		2 / 2 = 1 ...... 0
		3 / 1 = 3 ...... 0
		3 / 2 = 1 ...... 1
		3 / 3 = 1 ...... 0
		4 / 1 = 4 ...... 0
		4 / 2 = 2 ...... 0
		4 / 3 = 1 ...... 1
		4 / 4 = 1 ...... 0
		.......
	上述分析:
		外层循环:被除数
		内层循环:除数
*/
public class BasicDemo04 {
	public static void main (String[] args) {
		int c = 0;
        
		/*
		for (int i = 1; i <= 100 ; i++ ) {
			//声明初始化整除次数的计数器变量
			int count = 0;

			for (int j = 1; j <= i; j++) {
				c++;

				if (i % j == 0) {
					count++;
				}
			}

			if (count == 2) {
				System.out.println(i);
			}
		}
		System.out.println(c);//5050
		*/

		//循环次数:1133
		for (int i = 2; i <= 100 ; i++ ) {
			//给每个被除数设置一个标记,默认所有的整数都是质数
			boolean flag = true;

			for (int j = 2; j < i; j++) {
				c++;

				if (i % j == 0) {
					flag = false;
					break;
				}
			}

			if (flag) {
				System.out.println(i);
			}
		}

		System.out.println(c);
	}
}

  • 打印九九乘法表:

/*
九九乘法表 外层循环:行
		 内层循环:列
*/

public class BasicDemo05 {
	public static void main (String[] args) {
		for (int hang = 1; hang <= 9; hang++) {
			for (int lie = 1; lie <= hang ; lie++ ) {
				System.out.print(lie + "*" + hang + "=" + hang * lie + "\t");
			}
			System.out.println();
		}
	}
}

方法

定义

method是执行特殊功能的代码块

好处

  • 提高代码的复用性,从而提高开发效率
  • 将功能性代码抽取出来,有效的降低代码的耦合性(降低代码与代码之间的依赖)

声明格式

​ 修饰符public static 返回值类型 方法名 (形参类型1 形参名1,形参类型2 形参名2,…) {
​ 方法体语句
return 返回值;//有返回值则返回给调用者,无则由return结束方法
​ }

方法的传参和返回

  • 传参: 调用者方法的==数据 > 自定义方法
  • 返回: 自定义方法的==结果 > 调用者方法

声明前的两个明确

  • 返回值类型:

    • 基本数据类型
    • 引用数据类型
    • 没有返回值
  • 形参列表:

    • 需要用到调用者方法中的几个数据
    • 每个数据类型的数据类型和变量名

方法特点

不调用不执行

方法的调用方式(3*3)

  • 如果方法属于类,调用方式:
    类名.方法名(实参);

  • 如果方法属于对象,调用方式:

    ​ 对象名.方法名(实参);

    (以上类和对象未学)


  • 如果调用同一个类中方法:

    • 单独调用(直接调用)
      方法名(实参);
    • 输出调用(打印调用)
      System.out.println(方法名(实参));
    • 赋值调用
      数据类型 变量名 = 方法名(实参);

调用举例:通过方法完成两个整数求和计算

  • 代码
public class MethodDemo02 {
	public static void main (String[] args) {
		//单独调用(直接调用)
		//getSum(3,4);
		//输出调用
		//System.out.println(getSum(3,4));
		//赋值调用
		int sum = getSum(3,4);
		System.out.println(sum);
	}

	/*
		两个明确:
			返回值类型:int
			形参列表: int a , int b
	*/
	public static int getSum (int a , int b) {
		int sum = a + b;
		return sum;
	}
}
  • 方法调用的内存图解
    在这里插入图片描述

void关键字

  1. 声明方法时,如果方法没有返回值,返回值类型的位置也不能空着,需要使用void关键字进行占位(void即表示方法没有返回值)
  2. 当方法返回值类型是void时,调用方式只能是单独调用,否则编译报错
  3. 当方法返回值类型是void时,return语句可以省略不写

举例说明:打印指定次数的HelloWorld

*/
public class MethodDemo05 {
	public static void main (String[] args) {
		print(10);
	}

	/*
		两个明确:
			返回值类型:void
			形参列表: int num
	*/

	public static void print (int num) {
		for (int i = 1; i <= num ; i++ ) {
			System.out.println("HelloWorld");
		}

		return;
        //System.out.println("111111");return后不能写代码,return结束了方法
	}
}

方法的重载

方法的重载:在同一个类中(或子父类继承关系中),出现方法名相同,形参列表不同的现象

  • 方法重载的注意事项:

方法重载的注意事项:
1.必须在同一个类中(或子父类继承关系中)
2.方法名必须相同
3.形参列表必须不同(必须满足以下至少一点)
a.形参的个数不同
b.形参的数据类型不同
c.形参数据类型的顺序不同
4.重载方法的调用取决于调用方法时的实参,根据实参匹配合适的方法

  • 方法重载练习
public class MethodDemo07 {
	public static void main (String[] args) {
        method(123);
        /*结果为int;若实参改为强制转换(byte)123的同时去掉byte方法,按day02的内容:当byte,short,char参与数学运算则结果自动越级为int,此处没有数学运算,所以实参数据类型由byte提升为short,则匹配short方法,调用short方法后输出short.
        */
		//method(3,4);//A int double B double int//虚拟机不知道提升3还是4,报错 
		//System.out.println(null);//引用不明确,报错,同上
	}
    public static void method (int a , double b) {
		System.out.println("int double");
	}

	public static void method (double a, int b) {
		System.out.println("double int");
	}
    /*
	public static void method (int a , int b) {
		System.out.println("int int");
	}

	public static void method (double a, double b) {
		System.out.println("double double");
	}
	*/
    //针对以上两种方法,若实参为(3,4.5),输出double double
    public static void method (byte num) {
		System.out.println("byte");
	}
	
	public static void method (short num) {
		System.out.println("short");
	}

	public static void method (int num) {
		System.out.println("int");
	}

	public static void method (long num) {
		System.out.println("long");
	}
}	

方法的总结

​ 1.方法声明的位置:类中,方法外;在程序中不可以形成方法的嵌套
​ 2.当进行方法声明的时候,返回值类型如果没有的话,也不能空着,需要使用void关键字进行替代
​ 3.当方法返回值类型是void时,方法中return关键字可以省略不写
​ 4.在方法中可以存在多个return语句,但是最终执行的只有唯一的一个
​ 5.当方法返回值类型是void时,方法的调用方式"只能"使用单独调用(直接调用)
​ 当方法返回值类型不是void时,方法的调用方式"推荐"使用赋值调用

​ 6.方法的形参可以没有

方法的递归

方法的递归:在程序中出现方法自身调用自身的一种现象

递归分类

  • 直接递归:方法自身调用自身
  • 间接递归:方法A调用方法B,B调用方法C,方法C调用方法A

使用递归的前提条件

​ 使用递归必须给其添加结束条件,否则会导致栈内存溢出
​ 递归的层数不能过多,即使添结束条件,也会导致栈内存溢出

递归的好处

​ 可以帮助我们解决一些使用循环语句无法解决的问题
​ 例如:
​ 操作多级文件夹
​ 伪代码:
​ public static void getPath (路径) {
​ 获取当前路径所有的文件以及文件夹

			遍历获取的容器
			if (是否为文件) {
				打印文件路径
			} else {
				打印文件夹路径
				getPath(新路径);
			}
		}
  • 求1到指定数之前的累加和
public class MethodDemo10 {
	public static void main (String[] args) {
		int sum = getSum(5);
		System.out.println("sum = " + sum);
	}

	/*
		两个明确:
			返回值类型:int
			形参列表: int num
	*/
	public static int getSum (int num) {
		if (num == 1) {
			return 1;
		}

		return num + getSum(num - 1);
	}


	public static int add (int num) {
		int sum = 0;

		for (int i = 1 ; i <= num ; i++ ) {
			sum += i;
		}

		return sum;
	}
}

代码执行图解
在这里插入图片描述

递归的弊端:斐波那契数列

  • 需求:

有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问指定月份的兔子对数为多少?

规律:
第一个月:1
第二个月:1
第三个月:2
第四个月:3
第五个月:5
第六个月:8

规律:从第三个月开始,每个月的兔子对数是前两个月的兔子对数之和,且第一个月和第二个月的兔子对数都是1

  • 代码
public class MethodDemo11 {
	//声明方法调用次数的变量
	static long count = 0;
	public static void main (String[] args) {
		//获取此时以纳秒为单位的时间  1秒=1000毫秒 1毫秒=1000微秒 1微秒=1000纳秒
		long start = System.nanoTime();
		long num = getNum02(50);
		//获取此时以纳秒为单位的时间
		long end = System.nanoTime();
		
		System.out.println("兔子的总对数:" + num);
		System.out.println("方法调用次数:" + count);
		System.out.println("程序运行时间:" + (end - start));
	}

	/*
		两个明确:
			返回值类型:long
			形参列表: int month
	*/

	/*
		兔子的总对数:12586269025
		方法调用次数:1          
		程序运行时间:8796       
	*/
	// 动态规划
	public static long getNum02 (int month) {
		count++;

		//当前月份兔子的对数
		long temp = 0;
		//上个月兔子的对数
		long a = 1;
		//上上个月兔子的对数
		long b = 1;

		if (month == 1 || month == 2) {
			return 1;
		}

		for (int i = 3; i <= month ; i++) {
			temp = a + b;
			b = a;
			a = temp;
		}

		return temp;
	}

	/*
		兔子的总对数:125.8626.9025 
		方法调用次数:251.7253.8049 
		程序运行时间:63784380668 
	*/
	public static long getNum01 (int month) {
		count++;

		if (month == 1 || month == 2) {
			return 1;
		}

		return getNum01(month - 1) + getNum01(month - 2);
	}
}
举报

相关推荐

0 条评论