第7章 方法:把复杂程序拆成小块

发布时间:2026/6/25 16:05:03
第7章 方法:把复杂程序拆成小块 第7章 方法把复杂程序拆成小块到目前为止我们已经能写输入、输出、条件、循环。问题是如果所有逻辑都写在main方法里代码会越来越长。比如一个注册程序publicclassRegisterDemo{publicstaticvoidmain(String[]args){Stringphone13800000000;Stringpassword123456;intage20;if(phonenull||phone.length()!11||!phone.startsWith(1)){System.out.println(手机号不合法);return;}if(passwordnull||password.length()6){System.out.println(密码不合法);return;}if(age18){System.out.println(未满18岁);return;}System.out.println(注册成功);}}现在还能读。规则再多十条main 就会变成一大坨。方法就是用来拆分逻辑的。一、方法是什么方法是一段有名字的代码。publicstaticvoidsayHello(){System.out.println(Hello);}调用sayHello();完整程序publicclassMethodDemo{publicstaticvoidmain(String[]args){sayHello();sayHello();}publicstaticvoidsayHello(){System.out.println(Hello);}}输出Hello Hello方法的价值避免重复。给逻辑起名字。降低主流程复杂度。让代码更容易测试。二、方法的结构publicstaticvoidsayHello(){System.out.println(Hello);}可以拆成public static 返回值类型 方法名(参数列表) { 方法体 }第一阶段我们先统一使用public static。public和static后面面向对象阶段再深入。现在重点看返回值类型。方法名。参数列表。方法体。三、参数方法的输入没有参数的方法只能做固定事情publicstaticvoidprintTom(){System.out.println(Tom);}有参数的方法更灵活publicstaticvoidprintName(Stringname){System.out.println(姓名name);}调用printName(Tom);printName(Jack);多个参数publicstaticvoidprintUser(Stringname,intage){System.out.println(姓名name);System.out.println(年龄age);}参数是调用方传给方法的数据。方法不要总是依赖写死的数据。四、返回值方法的输出没有返回值用voidpublicstaticvoidprintLine(){System.out.println(------);}有返回值publicstaticintadd(inta,intb){returnab;}调用intresultadd(3,5);System.out.println(result);返回值让方法可以参与后续计算而不是只能打印。不推荐把计算和打印绑死publicstaticvoidaddAndPrint(inta,intb){System.out.println(ab);}更好publicstaticintadd(inta,intb){returnab;}外层决定怎么输出。五、return 的两个作用1. 返回结果publicstaticintmax(inta,intb){if(ab){returna;}returnb;}2. 提前结束方法publicstaticvoidcheckAge(intage){if(age18){System.out.println(未满18岁);return;}System.out.println(可以注册);}return 后方法立即结束。六、方法命名方法名要表达动作。好名字isValidPhonecalculateTotalPriceprintMenureadScorefindMaxScore差名字doIthandleaaatest布尔返回值方法常用publicstaticbooleanisAdult(intage){returnage18;}publicstaticbooleanhasPermission(booleanlogin,booleangranted){returnlogingranted;}读起来像问题是否成年是否有权限七、方法重载同名方法参数不同叫重载。publicstaticintadd(inta,intb){returnab;}publicstaticintadd(inta,intb,intc){returnabc;}publicstaticdoubleadd(doublea,doubleb){returnab;}调用时编译器根据参数选择方法。System.out.println(add(1,2));System.out.println(add(1,2,3));System.out.println(add(1.5,2.5));重载适合同一语义、不同参数形式。不要用重载表达完全不同的事。八、作用域方法里的变量只在方法内部有效。publicstaticvoidtest(){intcount10;}publicstaticvoidmain(String[]args){// System.out.println(count); // 错误}代码块里的变量也只在块内有效if(true){intvalue100;}// System.out.println(value); // 错误变量作用域越小代码越容易理解。不要把变量提前定义到很大范围。九、基本类型参数和引用类型参数基本类型publicclassParamDemo{publicstaticvoidmain(String[]args){intage18;change(age);System.out.println(age);}publicstaticvoidchange(intvalue){value20;}}输出18方法里改的是副本不影响外面的 age。数组是引用类型publicclassArrayParamDemo{publicstaticvoidmain(String[]args){int[]scores{60,70};change(scores);System.out.println(scores[0]);}publicstaticvoidchange(int[]values){values[0]100;}}输出100因为方法内外指向同一个数组对象。第一阶段先记住基本类型传进去不会改外部变量数组这类引用类型修改内容会影响外部对象。十、把注册逻辑拆成方法publicclassRegisterMethodDemo{publicstaticvoidmain(String[]args){Stringphone13800000000;Stringpassword123456;intage20;if(!isValidPhone(phone)){System.out.println(手机号不合法);return;}if(!isValidPassword(password)){System.out.println(密码不合法);return;}if(!isAdult(age)){System.out.println(未满18岁);return;}System.out.println(注册成功);}publicstaticbooleanisValidPhone(Stringphone){returnphone!nullphone.length()11phone.startsWith(1);}publicstaticbooleanisValidPassword(Stringpassword){returnpassword!nullpassword.length()6;}publicstaticbooleanisAdult(intage){returnage18;}}主流程现在很清楚校验手机号 - 校验密码 - 校验年龄 - 注册成功每个规则单独放在方法里后面修改也更方便。十一、方法的单一职责一个方法最好只做一件事。不推荐publicstaticvoidvalidateAndSaveAndPrint(Stringphone){}这个名字已经说明它做太多事校验、保存、打印。更好publicstaticbooleanisValidPhone(Stringphone){}publicstaticvoidsavePhone(Stringphone){}publicstaticvoidprintSuccess(){}单一职责的好处容易命名。容易测试。容易复用。容易排查。如果一个方法很难起名通常说明它职责不清。十二、方法实战成绩统计拆分publicclassScoreMethodDemo{publicstaticvoidmain(String[]args){int[]scores{90,85,70,60};System.out.println(最高分findMax(scores));System.out.println(最低分findMin(scores));System.out.println(平均分calculateAverage(scores));}publicstaticintfindMax(int[]scores){intmaxscores[0];for(intscore:scores){if(scoremax){maxscore;}}returnmax;}publicstaticintfindMin(int[]scores){intminscores[0];for(intscore:scores){if(scoremin){minscore;}}returnmin;}publicstaticdoublecalculateAverage(int[]scores){intsum0;for(intscore:scores){sumscore;}returnsum*1.0/scores.length;}}这里还有一个问题如果 scores 是空数组会出错。更严谨的版本要加校验。阶段项目里会处理。十三、常见错误1. 有返回值却忘记 returnpublicstaticintadd(inta,intb){intresultab;}声明返回 int就必须 return int。2. return 类型不匹配publicstaticintgetAge(){return18;}字符串不能作为 int 返回。3. 参数顺序传错calculatePrice(count,unitPrice);如果两个参数都是 int编译器可能发现不了语义错误。方法名、参数名要清楚参数太多时后面要用对象封装。4. 方法太长一个方法超过几十行就要考虑能不能拆。5. 方法名和行为不一致isValidPhone里不要保存数据。方法名承诺了它只是校验。十四、本章练习写方法isEven(int number)判断偶数。写方法max(int a, int b)返回较大值。写方法calculateBmi(double height, double weight)。写方法getScoreLevel(int score)返回优秀、良好、及格、不及格、非法。把注册校验拆成三个方法手机号、密码、年龄。给成绩数组写三个方法最高分、最低分、平均分。十五、本章总结方法是组织代码的第一把工具。你需要掌握方法是一段有名字的代码。参数是输入。返回值是输出。void 表示没有返回值。return 可以返回结果也可以结束方法。方法名要表达意图。方法重载适合同一语义的不同参数。变量有作用域。基本类型和引用类型作为参数表现不同。方法要尽量单一职责。下一章是第一阶段项目。我们会把输入、条件、循环、方法组合起来写一个命令行成绩统计器。