考试通知
0基础学习java第二天最容易出现的状态不是“看不懂”而是“好像都认识但写不出东西”。昨天刚配好java环境变量跑通了Hello World也分清int、double、boolean这些基本类型今天一打开编辑器面对空白的main方法反而不知道该写点什么。这不是你笨而是从“认识语法”到“组织逻辑”之间有一道坎第二天的任务就是专门把这层窗户纸捅破顺序、分支、循环、数组、方法今天搞定这五样你就能独立写出带判断和重复逻辑的小程序了。这篇内容就是照着0基础学习java第二天的实际进度把我带新手时反复讲的重点、踩过的坑、以及最后能直接上手的练习一次性整理出来。1. 第二天该学什么先想清楚“代码是怎么跑起来的”很多新手第一天结束的时候对Java的印象是“一堆单词和符号”。变量像是一个盒子int放整数double放小数字符串用String。但盒子有了怎么让这些盒子之间产生关系怎么让程序按照你的想法去执行这就要提到“程序三大结构”顺序、分支、循环。1.1 顺序执行是默认规则Java程序的默认执行方式就是从上到下一行一行执行。就像你早上起床睁眼、摸手机、看时间、决定要不要再睡五分钟。这就是顺序结构。看下面这段代码public class Day2Demo { public static void main(String[] args) { int age 20; System.out.println(我的年龄是 age); age age 1; System.out.println(明年我的年龄是 age); } }输出结果是两行第一行是“我的年龄是20”第二行是“明年我的年龄是21”。如果你把第三行和第四行换个位置输出就变了。这就是顺序结构听起来很简单但它是后面所有分支和循环的地基。如果你连“代码从上往下跑”这个直觉都没有后面写if的时候逻辑一定会乱。1.2 只有顺序结构的时候程序就是一张“便利贴”你想一下如果没有分支和循环你写一万行代码程序也是从头到尾执行一遍就结束了。那写一个“成绩判断”的小程序怎么办比如考试成绩90分以上显示优秀60分以下显示不及格。这种“根据条件做不同事”的需求顺序结构根本做不到。再比如你想输出1到10这十个数字顺序结构你得写十行System.out.println那如果输出1到1000呢手写到天亮都写不完。所以第二天一开始你就得接受一个观念编程的核心不是记住更多语法而是学会用分支和循环去控制代码的走向。这是从“会读代码”到“会写代码”的分水岭也是java基础里面最值得反复练的部分。1.3 第二天的路线和精力分配按照我带新手的经验第二天不用贪多踩踏实实走这几步就足够搞懂if-else和switch知道什么时候用哪个。搞懂for、while、do-while三种循环能把循环用对。搞懂数组能遍历数组、能对数组做简单操作。搞懂方法能自己定义方法、调用方法理解参数传递。用综合练习收尾把前面四个知识点串起来。如果你只把这一天的内容练熟第三天开始接触面向对象编程java就会非常轻松。很多初学者在面向对象那里崩溃回头一看其实是第二天的循环和数组没练扎实。别急着往前赶今天这几个知识点值得花一整天的实操时间。提示第一天没有配好Java环境变量的同学建议先回头把JDK安装和环境变量配置补上磨刀不误砍柴工。今天所有代码都需要能真实运行光看不敲等于白学。2. 分支判断写不对程序就走岔路if-else与switch实战2.1 if-else的基本写法不是每个条件都要写elseif-else是Java里最常用的分支结构基本格式是这样int score 75; if (score 90) { System.out.println(优秀); } else if (score 60) { System.out.println(及格); } else { System.out.println(不及格); }这里有个新手特别容易犯的错以为每个if后面都一定要跟一个else。不是的。如果你只是想在某种特殊情况下做一件事其他情况什么都不做那直接写一个单独的if就够了if (score 0) { System.out.println(分数不合法); }不带else的if非常常见很多新手不敢这么写总觉得缺了点什么。其实分支结构的核心就是条件成立就走if里的代码条件不成立就跳过该怎么样还怎么样。另一个新手常犯的坑是“分支顺序写反”。比如上面这个例子如果你先写if (score 60)再写else if (score 90)那考了95分的人也会走“及格”分支因为95满足 60。判断条件的时候程序是从上到下依次问的命中一个就结束不会再回头比较。所以写范围判断时要么从大到小排要么从小到大排别乱序。2.2 比较两个字符串别用双等号新手在分支这里第一个“翻车事故”十有八九是字符串比较。比如你想判断用户输入的名字是不是“admin”很多人会这么写String username admin; if (username admin) { System.out.println(欢迎回来); }这段代码在大多数时候居然能正常输出于是你就以为这么写是对的。直到某一天你把字符串从别的地方传过来比如从控制台读取或者从键盘输入就会发现同样的判断居然不生效了。原因在于比较的是“引用地址”而不是“内容”。字符串在Java里是对象两个内容相同的字符串可能是内存里的两个不同对象。正确的写法是用equals方法if (admin.equals(username)) { System.out.println(欢迎回来); }我建议把常量“admin”放在前面调用equals这样即使username是null也不会抛出空指针异常。这个习惯在你以后写java基础面试题的时候会经常碰到属于高频考点中的高频。2.3 浮点数比较的坑0.1加0.2不等于0.3除了字符串浮点数比较也是新手重灾区。Java里的double和float是二进制浮点数很多十进制小数没法被精确表示。你写0.1 0.2 0.3结果会是false。第一次见这个现象的人基本都会懵以为自己数学白学了。处理方式有两种如果比较的是两个double你可以比较它们的差值是否小于一个很小的误差范围比如Math.abs(a - b) 0.000001如果做的是金额相关的计算以后学了BigDecimal再回来收拾它。第二天你只需要知道浮点数不要直接用双等号比较。这个知识点同样会出现在java基础面试题里而且属于那种一问一个准的送分题。2.4 switch适合“一个变量多种取值”的场景if-else可以解决所有分支问题但有一种情况用switch更舒服同一个变量它可能有多个确定的值每个值对应不同逻辑。比如根据数字返回星期几int day 3; switch (day) { case 1: System.out.println(星期一); break; case 2: System.out.println(星期二); break; case 3: System.out.println(星期三); break; default: System.out.println(未知); break; }新手最容易漏的就是break。漏了break程序执行完当前case之后不会停下来会继续往下执行后面的case直到遇到break或者switch结束。这就是所谓的“穿透”。我记得以前带过一个学员写了个选择菜单的switch一直觉得程序“神经兮兮”的选1会执行完1的逻辑还顺手把2的逻辑也跑了。检查了半天才发现是case 1的break忘了写。这种问题靠肉眼看不出来但只要你记住“每个case结尾都写break”这条铁律就能避开。Java 12以后switch还支持了箭头语法可以不用写breakswitch (day) { case 1 - System.out.println(星期一); case 2 - System.out.println(星期二); default - System.out.println(未知); }这是新写法但第二天你只要先掌握传统写法就行知道有这种新语法以后自然能用到。3. 循环没那么简单for、while、do-while与死循环自救指南3.1 三种循环本质上是同一件事循环的作用一句话就能说清让一段代码重复执行。Java里有三种循环语句for、while、do-while。很多新手纠结“我到底该用哪个”其实它们的本质是一样的区别只在“你更清楚循环次数吗”和“至少要执行一次吗”。如果你明确知道循环要执行多少次比如输出1到100首选for。如果你不知道次数只知道条件比如一直读到用户输入exit才停首选while。如果你希望不管条件成立不成立循环体都先执行一次再判断要不要继续就用do-while。我建议第二天把精力重点放在for和while上。do-while是三者里用得最少的理解就行不强求熟练。3.2 for循环的三步走for循环的写法看起来很紧凑很多新手会觉得难记。其实它就是把循环控制的三个动作放在一行里了for (int i 1; i 10; i) { System.out.println(i); }拆开来看是三步第一步int i 1是初始化定义循环变量i并赋初值第二步i 10是循环继续的条件只要条件为true就执行循环体第三步i是每次循环体执行完后的更新动作。执行顺序是初始化 - 判断条件 - 执行循环体 - 更新 - 判断条件 - 执行循环体……这里有个百试百灵的调错方法不确定循环会跑多少次就自己拿一张纸把i的每一次变化写出来。比如上面这个循环i从1开始输出1后i变2输出2后i变3一直到i变成11条件11 10为false循环结束。你把这一行过程写在纸上循环的“手感”就有了。3.3 死循环是怎么来的死循环就是程序永远跳不出循环体一直跑。新手写死循环最常见的一个原因是在for循环里忘记写更新动作。比如for (int i 1; i 10; ) { System.out.println(i); }这里i永远是11 10永远成立程序就会一直输出1。控制台刷屏只能强制终止程序。在IDEA里点那个红色的停止按钮在命令行下按CtrlC。别慌每个写过循环的人都经历过死循环重点是你要能反应过来“是不是循环变量没更新”。还有一个更隐蔽的坑在while循环里用continue跳过了一些代码结果把更新语句也跳过去了。int i 0; while (i 10) { if (i 5) { continue; } System.out.println(i); i; }当i等于5的时候continue会让程序直接回到条件判断下面的i被跳过了于是i永远停在5死循环。这种问题光看很难发现排查的时候要重点检查continue、break和更新语句之间的关系。我的习惯是循环体的更新语句尽量放在循环体开头或者用for循环而不是while循环因为for的更新写在括号里不容易被continue跳掉。3.4 break和continue跳出循环还是跳过本次break和continue是两个容易混淆的关键字。break是“终止整个循环”continue是“跳过本次循环的剩余部分进入下一次循环”。用比喻来说break是你在跑步时接到电话说“停今天不用跑了”整个跑步过程结束continue是跑到第3圈时鞋带松了停下来系鞋带系完继续跑第4圈。看一个对比for (int i 1; i 5; i) { if (i 3) { break; } System.out.println(i); } // 输出 1 2 for (int i 1; i 5; i) { if (i 3) { continue; } System.out.println(i); } // 输出 1 2 4 5这两个关键字在刷java面试题和实际业务场景里出现频率极高。尤其是嵌套循环里使用break默认只跳出最内层循环这个知识点你现在可以不知道但心里要有个印象。第二天能分清break和continue的区别就已经达标了。4. 数组一上来就懵那是因为没搞懂内存和下标4.1 数组的本质一块连续内存 一张下标映射表数组是Java里最基础的数据容器。你可以把它理解成一排带编号的柜子编号从0开始而不是从1开始。第一个柜子是0号第二个是1号以此类推。这个“从0开始”就是对新手最不友好的设定。很多人的数组越界异常问题就出在这里明明创建了长度为5的数组却总想去访问第5个位置也就是下标5然后程序抛异常。int[] nums new int[5];这段代码干了三件事在内存里申请一块连续空间能放5个int用一个叫nums的变量指向这块空间把每个位置初始化成默认值0。int数组的默认值是0double数组默认值是0.0boolean数组默认值是falseString数组默认值是null。这些默认值在新手阶段可能用不到但面试里偶尔会问知道没坏处。4.2 三种初始化方式和遍历数组常见的初始化写法有三种// 方式一先声明再逐个赋值 int[] arr1 new int[3]; arr1[0] 10; arr1[1] 20; arr1[2] 30; // 方式二声明时就给初始值 int[] arr2 {10, 20, 30}; // 方式三用new加初始值 int[] arr3 new int[]{10, 20, 30};方式二是新手阶段用得最多的省事。遍历数组最稳的办法是用普通for循环配合arr.lengthfor (int i 0; i arr2.length; i) { System.out.println(arr2[i]); }注意数组的length是一个属性不是方法所以不用写length()。这个细节看着小但新手经常因为写括号报错。还有一种遍历方式是增强for循环也叫foreach只关心元素不关心下标for (int n : arr2) { System.out.println(n); }增强for循环适合“我就是想把每个元素读出来看一眼”的场景。但如果你想修改数组里的值比如把每个元素都翻倍增强for就不好使了因为里面那个n只是数组元素的副本。这种情况老老实实用普通for循环。4.3 数组越界程序崩溃最常见的原因之一数组越界是java基础里非常经典的一个运行时异常英文是ArrayIndexOutOfBoundsException。它发生的原因很简单你访问了下标范围之外的位置。比如数组长度是5有效下标是0到4你访问下标5就崩了。新手经常犯的一个错是把i arr.length写进循环条件int[] arr {10, 20, 30}; for (int i 0; i arr.length; i) { System.out.println(arr[i]); }这里i最大跑到3但arr的有效下标最大是2所以最后一次循环直接抛异常。正确写法是i arr.length。说实话这个错我到现在偶尔还能在经验比我少的同事代码里看到不是什么丢人的事关键是看到ArrayIndexOutOfBoundsException的时候脑子里的第一反应就是“循环边界写错了”。优先检查所有遍历数组的循环条件90%的情况一眼就能定位。4.4 实战练习翻转数组和找出最大值光说不练假把式。数组这块我推荐两个热身练习简单但很有代表性。第一个把数组元素倒序输出。int[] arr {1, 2, 3, 4, 5}; for (int i arr.length - 1; i 0; i--) { System.out.println(arr[i]); }第二个找出数组里的最大值和最小值。思路是先假设第一个元素最大然后拿它和后面的所有元素挨个比。int[] arr {3, 7, 2, 9, 5}; int max arr[0]; for (int i 1; i arr.length; i) { if (arr[i] max) { max arr[i]; } } System.out.println(最大值是 max);这两个练习不要只看一定要亲手敲一遍。尤其是第二个它涉及到“用一个变量记住中间结果”的思路这个思路后面学面向对象编程java的时候还会反复用到。你会在无数算法场景里看到“先假设一个最优值然后遍历更新它”这种模式。4.5 冒泡排序新手第一个排序算法如果你今天还有余力数组这一节可以顺手把冒泡排序写了。冒泡排序的基本思想很直观相邻两个元素两两比较如果顺序不对就交换位置。每一轮比较下来最大的数就像气泡一样浮到最右边。第二轮的比较范围就可以缩掉最右边的那个数因为它是最大数不需要再参与比较了。int[] arr {5, 3, 8, 1, 2}; for (int i 0; i arr.length - 1; i) { for (int j 0; j arr.length - 1 - i; j) { if (arr[j] arr[j 1]) { int temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; } } } for (int n : arr) { System.out.print(n ); }冒泡排序在java课程设计案例源码里属于出现频率极高的基础算法。它效率不高时间复杂度是O(n²)但教学价值很大因为嵌套循环、数组下标访问、交换变量这三个操作全都能练到。新手写冒泡排序最容易出的问题是内层循环的结束条件写错j arr.length - 1 - i这个减i一定不能省。减i的意思就是“已经浮到右边的最大数不用再比了”。如果你不减i排序结果也是对的但会多做很多无用比较以后面试官问“怎么优化”你就可以从这里展开聊。5. 方法封装把重复代码关进黑盒参数传递和重载入门5.1 方法的三个核心要素方法这个概念其实你第一天就见过了main方法就是一个方法。方法的作用用一句话说就是把一段代码打包成一个“黑盒”给它起个名字需要的时候喊名字就能执行。方法可以接收输入数据也可以返回处理结果。定义一个方法的基本格式public static int add(int a, int b) { int sum a b; return sum; }拆解来看public是访问修饰符static是静态关键字int是返回值类型add是方法名括号里的int a, int b是参数列表方法体里通过return把结果返回。如果方法不需要返回任何东西返回值类型就写void这时可以不用写return语句。新手对方法最大的困惑是为什么要来回折腾直接在main里写不好吗答案是当代码超过一定规模以后如果不拆方法main方法就会变成一坨几百行的“意大利面条”改一个地方要上下翻半天。而且同样的逻辑写两三遍的时候你就要意识到该抽方法了。比如你现在要算三个矩形的面积每个矩形都要“长乘宽”这么一步。如果你把“算面积”抽成一个方法调用三次就行以后想改成“周长”只改方法里那一处不用改三个地方。5.2 值传递的真相为什么方法里改了外面没变这是java基础面试题里非常高频的一个考点但第二天你不用理解到很深的层次只需要记住一个现象Java的参数传递是值传递。对于基本类型方法拿到的是值的副本你在方法里怎么改外面的变量不受影响。public static void main(String[] args) { int num 10; change(num); System.out.println(num); // 输出还是10 } public static void change(int x) { x 20; }这里的num是10传给change方法后方法里的x变成了20但main里的num还是10。可以理解为change方法拿到的是num的“复印件”而不是原件。很多新手在这里会想不通其实你用“复印件”这个比喻去理解就通了你在复印件上涂改原件不会变。但是对于数组这种引用类型情况就不同了。引用类型变量存的是对象的地址方法参数复制的是这个地址。地址指向同一个数组对象所以你在方法里修改数组的元素外面的数组会跟着变。public static void main(String[] args) { int[] arr {1, 2, 3}; change(arr); System.out.println(arr[0]); // 输出100 } public static void change(int[] nums) { nums[0] 100; }我当初学这块的时候也绕了很久后来想明白一个关键点引用类型也是值传递只不过这个“值”是地址。地址一样大家操作的就是同一个对象。这个知识点以后学java对象深度拷贝的时候还会再遇到现在先把这个“复印件和原件”的关系记住。5.3 方法重载同名方法不同参数列表方法重载是Java里一个很实用的特性同一个类里可以定义多个同名方法只要它们的参数列表不同就行。比如public static int add(int a, int b) { return a b; } public static int add(int a, int b, int c) { return a b c; } public static double add(double a, double b) { return a b; }调用的时候Java会根据你传的参数个数和类型自动匹配对应的方法。你写add(1, 2)调第一个写add(1, 2, 3)调第二个写add(1.5, 2.5)调第三个。重载的存在就是为了让你不用给每个方法起不同的名字比如addInt、addDouble、addThreeInt用一套名字不同参数自动区分。System.out.println本身也是一个被重载的方法你传字符串、传整数、传小数它都能输出靠的也是重载。新手容易把重载和重写搞混。重写是面向对象里子类覆盖父类方法的机制最快要到第三天才接触。第二天你只需要会区分重载发生在“同一个类里”参数列表不同重写发生在“父类与子类之间”方法签名相同。这个区别是java面试八股文里的保留题目早接触早好。5.4 用方法组织代码的小习惯第二天写方法不用追求设计模式那些高级东西但有两个习惯可以早点养成。第一个习惯是“一个方法只做一件事”。比如一个计算平均分的方法就只负责计算别在里面又输出又排序又写文件。方法的责任越单一以后出问题越好定位。第二个习惯是“给方法起个能看懂的名字”。Java的命名习惯是首字母小写、后面每个单词首字母大写比如calcAverage、printArray。不要写a、b、c这种缩写。我带新手改代码时见过太多public static void dddd()这种方法名过两天本人回来都看不懂自己写的是什么。6. 实战验收用今天学的内容写一个猜数字小游戏6.1 需求拆解二手知识学得再多不写代码就等于白学。第二天的综合练习我强烈建议做这个“猜数字”小游戏因为它正好能把分支、循环、数组之外的方法调用、随机数、Scanner输入全部串起来。游戏规则很简单程序随机生成一个1到100之间的整数用户从键盘输入猜测的数字程序告诉用户“大了”还是“小了”直到猜对为止最后输出一共猜了几次。在写代码之前先别急着敲键盘试着拆一下需求需求一生成随机数。用Random类nextInt(100)生成的是0到99的整数加1就是1到100。需求二读取用户输入。用Scanner类的nextInt()方法。需求三比较逻辑。用if-else判断“大了”、“小了”、“猜对了”。需求四重复猜。用while循环条件是“没猜对就继续”。需求五统计次数。用一个变量记录循环次数。拆完以后你会发现今天学的知识点正好全都不浪费。6.2 完整代码import java.util.Random; import java.util.Scanner; public class GuessNumber { public static void main(String[] args) { Random random new Random(); int target random.nextInt(100) 1; Scanner scanner new Scanner(System.in); int guess 0; int count 0; System.out.println(我已经想好了一个1到100之间的数字你来猜猜看); while (guess ! target) { System.out.print(请输入你的猜测); guess scanner.nextInt(); count; if (guess target) { System.out.println(大了再往小一点猜); } else if (guess target) { System.out.println(小了再往大一点猜); } else { System.out.println(恭喜你猜对了); } } System.out.println(你一共猜了 count 次); scanner.close(); } }这段代码不长但它非常值得你亲手敲一遍不要复制。敲的过程中你会遇到一堆小问题Scanner怎么导包、while条件里的变量guess初始化成0会不会有问题、scanner.close()到底要不要写。这些问题都是宝贵的遇到一个解决一个你的手感就慢慢有了。6.3 进阶改造方向基础版跑通以后我建议你做两个小改造。第一个改造限制猜测次数。比如最多猜10次超了就算失败。这个需要用到break你得在while循环里加一个次数判断超过10次就break退出然后输出“游戏结束正确答案是X”。这个改造练的是break和循环条件的结合。第二个改造把“比较大小”的逻辑抽成一个方法。public static String checkGuess(int guess, int target) { if (guess target) { return 大了; } else if (guess target) { return 小了; } else { return 猜对了; } }然后主循环里直接调用这个方法根据返回值再做输出。这个改造练的就是今天刚学的方法封装。你会发现主方法一下子清爽了很多以后代码逻辑变复杂时你就能体会到拆方法的好处了。到了这一步第二天该学的核心内容已经全部过了一遍。如果你今天能把猜数字代码独立写出来并且理解每一步为什么这么写那你的进度已经超过很多自学两三天的人。第二天没必要急着去看面向对象、StringBuilder那些进阶内容。我个人的建议是晚上再花一个小时把白天的代码重新敲一遍不要看任何参考能默写出来才算真正吸收。编程这个东西看十遍不如敲一遍敲错一遍比看对十遍更有价值。
零基础学Java第二天:分支循环数组方法实战,写出猜数字游戏
NEXT STEP
看完公告,下一步怎么走?
把报考交给靠谱的人:材料预审、批次抢报、考前辅导、复审提醒,全程有人跟。