【学习记录5】控制语句学习(下)、方法、递归算法
一、嵌套循环循环语句内部再写一个或多个循环称为嵌套循环。一般工作中多见的就是两层。【示例1-1】嵌套循环for(int m1;m5;m){ for(int i0;i5;i){ System.out.print(m\t); } System.out.println(); }运行结果1 1 1 1 12 2 2 2 23 3 3 3 34 4 4 4 45 5 5 5 5【示例1-2】使用嵌套循环实现九九乘法表//打印九九乘法表 for(int m1;m9;m){ for(int n1;nm;n){ System.out.print(n*m(n*m10?( n*m):(n*m))\t); //如果结果为单位数则在结果前加一个空格 } System.out.println(); }运行结果1*1 11*2 2 2*2 41*3 3 2*3 6 3*3 91*4 4 2*4 8 3*412 4*4161*5 5 2*510 3*515 4*520 5*5251*6 6 2*612 3*618 4*624 5*630 6*6361*7 7 2*714 3*721 4*728 5*735 6*742 7*7491*8 8 2*816 3*824 4*832 5*840 6*848 7*856 8*8641*9 9 2*918 3*927 4*936 5*945 6*954 7*963 8*972 9*981本节练习使用嵌套循环打印输出5×5的方阵格式如下使用嵌套循环打印输出5*5的方阵格式如下for(int m1;m5;m){ for(int i1;i5;i){ if((mn)%20){ System.out.print(*\t); }else{ System.out.print(#\t); } } System.out.println(); }二、break语句和continue语句1. break用于强行退出整个循环【示例2-1】break语句public class TestBreak { public static void main(String[] args){ int total 0; //循环的总数 while(true){ total; int i (int)(Math.random()*100); System.out.println(i); if(i88){ break; } } System.out.println(循环次数total); } }运行结果72537836145354762970329188循环次数142. continue用于结束本次循环继续下一次continue语句用在循环语句体中用于终止某次循环过程即跳过循环体中尚未执行的语句接着进行下一次是否执行循环的判定。【示例2-2】continue语句/** * 测试Continue语句 * 把100~150之间不能被3整除的数输出并且每行输出5个 */ public class TestContinue { public static void main(String[] args){ int count 0; for(int i100;i150;i){ if(i%30){ continue; }else{ System.out.print(i ); count; if(count5){ System.out.println(); count0; } } } } }运行结果100 101 103 104 106107 109 110 112 113115 116 118 119 121122 124 125 127 128130 131 133 134 136137 139 140 142 143145 146 148 149带标签的continue语句“标签”是指后面跟一个冒号的标识符例如label:。对Java来说唯一用到标签的地方是在循环语句之前。goto有害论中最有问题的就是标签而非goto随着标签在一个程序里数量的增多产生错误的机会也越来越多。但Java标签不会造成这方面的问题因为它们的活动场所已被限死不可通过特别的方式到处传递程序的控制权。【示例2-3】带标签的continue——控制嵌套循环跳转(打印101-150之间所有的质数)outer:for(int i101;i150;i){ for(int j2;ji/2;j){ if(i%j0){ continue outer; //符合某条件跳到外部循环继续 } } System.out.print(i ); }运行结果101 103 107 109 113 127 131 137 139 149三、方法1. 语句块语句块也叫复合语句。语句块中定义的变量只能用于自己外部不能使用。语句块可以使用外部的变量而外部不能使用语句块的变量【示例3-1】语句块public class Test19 { public static void main(String[ ] args) { int n; int a; { int k; int n; //编译错误不能重复定义变量n } //变量k的作用域到此为止 } }2. 方法方法(method)一段用来完成特定功能的代码片段类似于其它语言的函数(function)。方法用于定义该类或该类的实例的行为特征和功能实现。面向过程中函数是最基本单位整个程序由一个个函数调用组成。面向对象中整个程序的基本单位是类方法是从属于类和对象的。方法声明格式[修饰符1 修饰符2 …] 返回值类型 方法名(形式参数列表){Java语句… … …}方法的调用方式普通方法对象名*.*方法名(实参列表)静态方法类名.方法名(实参列表)方法的详细说明形式参数在方法声明时用于接收外界传入的数据。方法定义时实参调用方法时实际传给方法的数据。 (方法调用时)返回值执行完毕后返还给调用它的环境的数据。返回值类型事先约定的返回值的数据类型如无返回值则为void。【示例3-2】方法的声明及调用/** * 测试方法定义与调用 */ public class TestMethod { public static void main(String[] args){ sayLoveU(); add(10,20,30); //add(10,20,30) add(100,200,300); } public static void sayLoveU(){ System.out.println(I Love U!); System.out.println(我爱你!); System.out.println(520); } public static int add(int a,int b,int c){ int sum abc; System.out.println(sum:sum); return sum; //return两个作用返回值结束方法运行 } }运行结果I Love U!我爱你!520sum:60sum:600注意事项实参必须和形参列表匹配。return终止方法运行并返回的数据。Java中传递参数遵循值传递的原则(传递的都是数据的副本)基本类型传递的是该数据值的copy值。引用类型传递的是该对象引用的copy值但指向的是同一个对象。【示例3-3】定义一个方法处理公司的吃到问题1输入吃到时间月薪。 2处理逻辑 迟到1-10分钟警告。 迟到11-20分钟罚款100元。 迟到21-30分钟罚款200元。 迟到30分钟以上扣除半日工资。 迟到1小时以上按照矿工计算扣除3日工资。 3输出罚款金额public class TestMethod2 { public static void main(String[] args){ int a handleLate(25,8000); int b handleLate(45,30000); int c handleLate(65,20000); System.out.println(今天公司罚款总数(abc)); } public static int handleLate(int lateMinute,int monthSalary){ int fakuan 0; int daySalary (int)(monthSalary/22.5); //全年工作日的平均数 System.out.println(迟到分钟数lateMinute); System.out.println(月薪monthSalary); if(lateMinute10) { System.out.println(警告!); }else if(lateMinute20){ fakuan 100; System.out.println(罚款100元!); }else if(lateMinute30){ fakuan 200; System.out.println(罚款200元!); }else if(lateMinute60){ fakuan daySalary/2; System.out.println(罚款fakuan元!); }else{ fakuan daySalary*3; System.out.println(按照矿工计算罚款fakuan元); } return fakuan; } }运行结果迟到分钟数25月薪8000罚款200元!迟到分钟数45月薪30000罚款666元!迟到分钟数65月薪20000按照矿工计算罚款2664元今天公司罚款总数35303. 方法的重载(overload)重载一个类中可以定义多个名称相同但形式参数列表不同的方法。新手雷区重载的方法实际是完全不同的方法只是名称相同而已构成方法重载的条件形参列表不同的含义形参类型、形参个数、形参顺序不同只有返回值不同不构成方法的重载如int a(String str){}与void a(String str){}不构成方法重载只有形参的名称不同不构成方法的重载如int a(String str){}与int a(String s){}不构成方法重载【示例】方法重载//形参类型、形参个数、形参顺序不同 public class TestOverLoad { public static void main(String[] args){ add(10,20); add(10); add(3.2); add(10,3.2); add(3.2,10); } static void add(int a,int b){ } static void add(int a){ } static void add(double a){ } static void add(int a,double b){ } static void add(double a,int b){ } }四、递归结构递归是一种常见的算法思路在很多算法中都会用到。比如深度优先搜索DFS:Depth First Search等。递归的基本思想就是“自己调用自己”。递归结构包括两个部分1. 定义递归头解决什么时候不调用自身方法。如果没有头将陷入死循环也就是递归的结束条件。2. 递归体解决什么时候需要调用自身方法。【示例】使用递归求5!public class Test22 { public static void main(String[] args){ long starTime System.currentTimeMillis(); //获得当前时刻 long result factorial(10); long endTime System.currentTimeMillis(); //当前时刻 System.out.println(阶乘的结果result); System.out.println(耗时(endTime-starTime)); } //阶乘5*4*3*2*1 public static long factorial(int n){ if(n1){ return 1; }else{ return n*factorial(n-1); } } }运行原理递归的缺陷算法简单是递归的优点之一。但是递归调用会占用大量的系统堆栈内存耗用多在递归调用层次多时速度要比循环慢的多所以在使用递归时要慎重。比如上面的递归耗时558ms(看电脑配置)。但是用普通循环的话快得多如下所示。【示例】使用循环求5!long t1 System.currentTimeMillis(); int a5; long result 1; while(a1){ result * a*(a-1); a - 2; } long t2 System.currentTimeMillis(); System.out.println(阶乘的结果result); System.out.println(普通循环耗时(t2-t1));

相关新闻