循环
死循环
- 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关键字
- 声明方法时,如果方法没有返回值,返回值类型的位置也不能空着,需要使用void关键字进行占位(void即表示方法没有返回值)
- 当方法返回值类型是void时,调用方式只能是单独调用,否则编译报错
- 当方法返回值类型是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);
}
}