☰
Java自学Day2:吃透变量、数据类型与流程控制,打好基础地基
2026/10/11 9:10:01 网站建设 项目流程

很多人学Java的第一天是满怀兴奋的:装好JDK、配好环境变量、弹出黑窗口跑出"Hello World",成就感满满。到了第二天往往就有点迷茫——文件建好了,代码也照着敲了,但总感觉这些东西连不成一条线。这篇文章就是我自己的Day2学习记录,也是踩过坑之后的整理。第二天的核心任务不再是"照抄代码跑通",而是要开始理解程序背后的逻辑骨架:变量是什么、数据类型有什么用、程序怎么根据条件做判断、又怎么重复执行一件事。

如果你正在按常见的学习路线自学Java,欢迎拿这一天作为参考。要想清楚的是:Day2打的地基直接决定了你后面学面向对象、集合框架、异常处理时是轻松衔接还是寸步难行。很多热词里提到的"java基础知识总结超详细""java面试八股文",其实追到根源上,都在反复考察这一天学的东西。所以别急着追赶进度,这一天的每个细节都值得认真抠一抠。

1. Day2到底该学什么:先定边界,再谈努力

1.1 把Day2放进完整学习路线里看

我在Day1做的事情很简单:装JDK、配环境变量、用记事本写了一个HelloWorld,然后装上了IntelliJ IDEA,熟悉了一下界面。到了Day2,我翻了一圈网上的"java自学路线图",发现几乎所有路线图在这个节点给的都是同一批内容:数据类型、变量、运算符、流程控制。这个设计不是巧合,这些就是Java程序的"骨架"。

变量和数据类型解决的是"程序里怎么存放数据",运算符解决的是"这些数据怎么计算",流程控制解决的是"程序到底走哪条路、重复执行哪段代码"。三者组合起来,你就能写出真正有逻辑的程序,而不是只会打印固定字符串。后面学的数组、方法、类,本质上都是在这套骨架上长肉。

所以Day2我给自己定了一个明确目标:不用UI、不做项目,就是干一件事——把"变量→计算→判断→循环"这条链路彻底吃透。目标越单一,反而越容易专注。

1.2 这些语法细节值得认真抠,不是"以后再说"

很多初学者有个错觉:语法细节嘛,用的时候查一下就行,先把东西做出来。这个想法在Day2是行不通的。因为后面所有的代码,包括集合遍历、算法题、框架源码,全部建立在这套语法上。我现在去看那些"java面试八股文",里面大量题目翻来覆去问的,其实就是数据类型范围、i++和++i的区别、短路逻辑、循环边界,全是Day2的东西。

另一个实际原因是手感。语法这个东西就像开车换挡,看别人换一百遍,和自己上手换十遍完全是两回事。Day2我开始给自己立规矩:每个知识点看完,必须立刻在IDEA里敲一遍,敲完再故意敲错几个版本,看看编辑器报什么错。这个习惯让我的学习效率提升了很多,报错信息读得多了,后面遇到问题反而不慌。

2. 开工前的隐藏关卡:JDK与环境变量配置的坑

2.1 JAVA_HOME、PATH、CLASSPATH到底谁管谁

严格说环境变量配置是Day1的活,但我Day2早上遇到的第一个坑就是它。昨天配置的时候随手填了一通,今天在命令行里敲java -version没问题,敲javac -version却提示找不到命令。这逼着我回头把环境变量的逻辑捋清楚。

三个变量各司其职:

  • JAVA_HOME:JVM安装的根目录,它不是给Java自己用的,而是给很多依赖Java的工具用的。Maven、Tomcat、IDEA都会去读这个变量来找JDK。
  • PATH:给操作系统用的。系统在命令行里执行命令时,会按PATH里列出的目录逐个找可执行文件。你敲java能找到,说明PATH里包含了JDK的bin目录。
  • CLASSPATH:给Java的解释器用的,告诉它去哪里找类文件。注意,JDK 1.5以后,如果没配CLASSPATH,JVM默认找当前目录;一旦你手动配了但配错了,反而会出问题。

我那个javac找不到,就是因为把PATH配错了地方。Windows用户在"环境变量"面板里改的是用户变量,而命令行窗口是在用户变量生效之前就打开的,所以我重新打开了一个cmd窗口就解决了。这个坑很隐蔽,网上搜"java环境变量配置"能搜到无数问这个问题的帖子,根源基本就两类:一是没重开终端,二是PATH拼写有空格或分号错误。

2.2 快速验证配置是否正确的办法

配置完之后,别再只敲java -version了,验证要带着javac一起看:

java -version javac -version

理想情况是两者的版本号完全一致。如果一个是17一个是1.8,八成是PATH里前面排了一个旧的JDK路径,把后面的覆盖了。这种多JDK版本冲突的问题,在Day2发现是好事,等到后面跑项目时再发现,排查成本高得多。另外可以顺手敲一句where java(Windows)或which java(macOS/Linux),确认用的到底是哪个目录下的JDK。

3. 数据类型与变量:Java的"身份证"逻辑

3.1 八大基本数据类型,一张表说清楚

Java被叫做强类型语言,意味着每一个变量都必须先声明类型。我开始觉得这个规矩麻烦,学完才明白这是Java比某些脚本语言更稳的根本原因。类型就是变量的一张身份证,决定了它能存什么值、占多大空间、能做什么运算。

我给自己做了一张表,贴在屏幕旁边,比翻书方便:

类型字节数取值范围/说明默认值
byte1-128 ~ 1270
short2-32768 ~ 327670
int4约 -21亿 ~ 21亿0
long8约 -922京 ~ 922京0L
float4约正负3.4E38,7~8位有效数字0.0f
double8约正负1.7E308,15~16位有效数字0.0d
char20 ~ 65535,单个字符'\u0000'
boolean1(由JVM决定)true / falsefalse

这张表看起来简单,但里面埋了三个坑:long不写L后缀、float不写F后缀、char只能装"单个"字符。我Day2写的第一段完整代码就是用基本类型做自我介绍,敲了下面这段:

public class SelfInfo { public static void main(String[] args) { int age = 25; double height = 178.5; char sex = '男'; boolean isStudent = false; long population = 14000000000L; float price = 99.9F; System.out.println("年龄:" + age); System.out.println("身高:" + height); System.out.println("性别:" + sex); System.out.println("是否学生:" + isStudent); System.out.println("人口:" + population); System.out.println("价格:" + price); } }

我故意把14000000000L不写L,编辑器直接报错"integer number too large",因为不加L时,字面量默认被当成int处理,而14亿明显超出了int的21亿上限吗?没超出,但超出的那些比如140亿就超出了。这个报错信息其实是在帮你避坑:Java里每一个数字字面量都有自己的类型,类型决定了它能容纳的上限。这是理解"强类型"的最直观入口。

3.2 类型转换:自动与强制,什么时候可以"不敲门"走进来

Java里类型转换有两条规则,我一开始记混了。后来用"大杯子小杯子"的类比才彻底分清:

  • 自动类型转换(隐式):小类型变量赋值给大类型变量时,Java自动转换。比如int装进long、double装进double,就像把小杯子的水倒进大杯子,稳稳的。
  • 强制类型转换(显式):大类型装进小类型,必须手动强转。比如double转int,就像把大杯子的水倒进小杯子,会溢出来——小数部分被截断。
double pi = 3.14159; int p = (int) pi; // p 变成 3,小数部分直接丢掉 System.out.println(p);

这里要特别提醒:强转不是四舍五入,是直接截断。我第一次敲这段时以为p会是4,结果是3,查了书才知道自己理解错了。这个细节在很多笔试选择题里反复出现,属于那种"看起来简单、错起来可惜"的知识点。另外char和int可以互相转换,字符本质上是Unicode编码对应的整数,比如(char) 65就是'A',(int) 'A'就是65,理解这个后面处理字符串和字符数组时很有用。

3.3 第一次接触引用类型:String和基本类型不是一类

Day2我第一次被"引用类型"这个概念冲击到。Java的数据类型分成两大类:基本类型和引用类型。基本类型存的是"值本身",引用类型存的是"地址"。就像你手里拿着一张写着门牌号的纸条(地址),而不是把房子搬在身上。

这个阶段不用深究内存细节,但String是绕不开的。字符串拼接这个操作就藏在两类数据转换的关口:"年龄:" + age里,int自动变成了String。Java在这里做了隐式的toString转换,这个机制我在Day2只需要有感知,真正的理解要等遇到"对象"之后。

有个小实验很值得做:把字符串和数字加在一起,看看结果是什么。

System.out.println(1 + 2 + "3"); // 结果是"33",不是6 System.out.println("1" + 2 + 3); // 结果是"123",不是"6"

因为+遇到第一个字符串后,整个运算就从加法变成了字符串拼接,后面的数字全被"吸"进字符串里了。这个细节很反直觉,但亲手敲一遍就记住了。老实说,这类"程序行为和直觉不一致"的瞬间,才是Day2真正有价值的学习点。

4. 运算符:看着简单,错起来最隐蔽

4.1 i++ 和 ++i:同一个梦魇

自增运算符是Java新手第一个真正意义上的"暗坑"。i++和++i区别在于:后置先返回原来的值,再自增;前置先自增,再返回新值。

我Day2写了一段代码来反复验证记忆:

int a = 5; int b = a++; // 先把5赋给b,然后a变成6 int c = ++a; // a先变成7,然后把7赋给c System.out.println("a=" + a + ", b=" + b + ", c=" + c);

结果是:a=7, b=5, c=7。第一次看到这个结果的时候我愣了半天,但这就是规则。这类题在面试八股文里出现频率极高,而且特别喜欢把它藏在复合表达式里,比如int result = i++ + ++i;,这种题目乍一看不合理,本质上就是在考察运算顺序和返回值的时机。

给我的建议是:不要在实际业务代码里写这种复合自增表达式,一行代码只做一件事,i++单独一行,不要嵌套进别的运算里。这既是为了别人读代码方便,也是给自己减少心智负担。

4.2 复合赋值运算符:有个隐藏的类型陷阱

+=、-=、*=、/=这类复合赋值,看起来就是"简化写法",但Java在底层帮你做了一个强制类型转换。这导致一个隐藏陷阱:

short s = 10; s = s + 5; // 报错!short + int结果是int,不能直接赋给short s += 5; // 合法!等价于 s = (short)(s + 5)

+=表面上是简写,实际上多了个隐式强转。知道这个规则之后,再看byte和short参与运算时的行为就容易理解了。Java里byte/short做算术运算时先自动提升为int,这也是很多奇怪报错的来源。

4.3 短路逻辑:&& 和 || 的"右边代码可能不执行"

逻辑运算符的短路特性,Day2如果不注意,等学到后面用JPA或者写判空逻辑时容易踩大坑。核心规则就两句话:

  • a && b:如果a为false,整个结果必为false,b根本不会执行。
  • a || b:如果a为true,整个结果必为true,b根本不会执行。

我敲了一段代码来感受短路:

int n = 10; boolean flag = (n > 5) || (n++ > 0); System.out.println(flag); // true System.out.println(n); // 还是10,因为 n++ 没执行!

第一次看到n还是10时我真的震惊了一下。这个特性用好了是优化,用不好就是隐蔽的bug。比如你想在一个条件里顺带做点副作用操作(改变某个变量的值),一旦触发短路,这个操作就悄悄失踪了。规范的做法是:副作用操作独立成行,不要放进条件表达式里。

4.4 三元运算符:if的"压缩饼干"

三元运算符条件 ? 值1 : 值2本质上是if/else的表达式版本,适合在赋值场景里做简单选择:

int score = 85; String level = score >= 60 ? "及格" : "不及格";

我Day2对它的态度是"可以会,但别滥用"。嵌套三元(a ? b : c ? d : e)看起来炫技,维护起来想骂人。后来我看到业界很多团队规范里明确写"禁止三元嵌套",深表认同。

5. 流程控制:让程序学会"判断"和"重复"

5.1 if/else if/else:不是你写几行代码,是你的思维顺序

流程控制最核心的不是语法,而是把现实中的条件逻辑拆解成程序能走的路径。我Day2练习判断成绩等级时写了这样一段:

Scanner sc = new Scanner(System.in); System.out.print("请输入成绩(0-100):"); int score = sc.nextInt(); if (score >= 90) { System.out.println("优秀"); } else if (score >= 80) { System.out.println("良好"); } else if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); }

这段代码虽然简单,但藏着两个重要的写代码习惯:

第一,自上而下的判断顺序就是逻辑优先级。如果把score >= 60放在第一个判断,那90分也会被判成"及格",因为第一个条件已经把它"截胡"了。条件判断是有顺序的,这个顺序决定了程序走的哪条路。

第二,用else收尾是个好习惯。哪怕你确信条件覆盖了所有可能,也建议留一个else兜底,这样程序在意外输入到来时不会无声无息地什么都不做。我在实际项目里见过很多因为条件盖不满导致"静默失败"的bug,根子就是少了else分支。

5.2 switch:漏掉break的连锁反应

把switch放在if后面学,两者正好形成对照。if是用"条件区间",switch擅长用"离散的值"来匹配。我Day2用switch做了简单的星期判断,然后故意漏掉break,看会发生什么:

int day = 3; switch (day) { case 1: System.out.println("星期一"); case 2: System.out.println("星期二"); case 3: System.out.println("星期三"); default: System.out.println("其他"); }

这段代码会打印"星期三"和"其他"两行。原因很直接:case只是入口,不是出口,匹配成功后代码会一路向下穿透,直到遇到break才停。这就是所谓的"case穿透"。防穿透的办法就是在每个case末尾补break,或者在JDK 12以后用箭头语法case 3 -> ...,箭头语法自带防穿透,比老式写法安全得多。

Day2这个节点,我的建议是把传统带break的写法练熟,至少要知道穿透现象是怎么发生的。因为老代码里满是这种写法,去读旧项目时看不懂就麻烦了。箭头语法是增强写法,知道存在即可,后面自然会用。

5.3 for/while/do-while:三种循环怎么选

三种循环都能做重复执行,但适用场景不同,我Day2用五个字记它们:

  • 我知道要做几次 →for
  • 我不知道几次,但条件满足就继续 →while
  • 无论如何先做一次再说 →do-while

这段笔记是在区分while和do-while时写的。while是先判断再执行,一次都不满足就一次都不执行;do-while是先执行再判断,至少执行一次。代码差异很微小,但语义完全不同,面试笔试里"以下哪个循环至少执行一次"的送分题问的就是do-while。

用for循环遍历和求和,是Day2练习量的主要来源:

int sum = 0; for (int i = 1; i <= 100; i++) { sum += i; } System.out.println("1到100的和为:" + sum);

这个经典求和,除了答案5050之外,我建议大家思考一个问题:sum为什么在循环外面定义?原因很简单——放在循环体内,每次循环都会把它重新初始化为0,前面累加的结果就全丢了。

5.4 break和continue:跳出循环的两个操作

Day2围绕循环还有一个绕不开的点:怎么中途改变循环流程。break是跳出整个循环,continue是跳过本次循环剩余代码、进入下一次循环。我用一段代码做了对比:

for (int i = 1; i <= 10; i++) { if (i == 5) { continue; // 跳过5,后面继续6、7... } if (i == 8) { break; // 到8直接整个循环结束 } System.out.println(i); // 打印1、2、3、4、6、7 }

结果打印了1、2、3、4、6、7。跳过5是因为continue,循环在8时结束是因为break。这两个关键字加上循环条件,就足够覆盖绝大部分循环控制场景了。我还特地试了下给循环加标签,也就是Java里很少见的"标签跳出嵌套循环"写法,能知道有这个语法就行,实际项目里几乎不用,用了反而被同事骂。

5.5 嵌套循环:九九乘法表是绕不开的练手项目

循环套循环,也就是嵌套循环,是Day2真正开始烧脑的地方。九九乘法表就是为嵌套循环量身定做的题目。我第一次写出来的时候歪歪扭扭(行对不齐),但逻辑通了之后非常兴奋:

for (int i = 1; i <= 9; i++) { for (int j = 1; j <= i; j++) { System.out.print(j + "*" + i + "=" + (i * j) + "\t"); } System.out.println(); // 一行结束换行 }

认真拆一下这个双重循环:外层i控制行数,内层j控制列数,内层循环用j <= i让每行的列数等于当前行号。这样第1行1列,第3行3列,正好打印出三角形的乘法表。这个题的价值不在于"会背代码",而在于它逼你搞清楚外层循环和内层循环的执行顺序:外层循环一次,内层循环要完整走一遍。这个执行顺序理解透了,后面学数组遍历、冒泡排序(你早晚会碰到这个热词)时就不慌。

6. 用三个小练习把Day2的知识钉进脑子里

6.1 练习一:判断水仙花数

水仙花数是经典的基础编程练习,Day2做它正好合适,因为它同时用到了取模%、整除/、if判断和数学思维。

Scanner sc = new Scanner(System.in); System.out.print("请输入一个三位数:"); int num = sc.nextInt(); int hundreds = num / 100; // 分解百位 int tens = num / 10 % 10; // 分解十位 int ones = num % 10; // 分解个位 int sum = hundreds * hundreds * hundreds + tens * tens * tens + ones * ones * ones; if (sum == num) { System.out.println(num + " 是水仙花数!"); } else { System.out.println(num + " 不是水仙花数。"); }

重点是分解三位的写法:/和%配合使用,一个是取商,一个是取余。num / 10 % 10的意思是用/10把十位变成个位,再用%10把高位全丢掉。把这个"除法+取模"的组合用熟,以后处理各种数值拆分都会很顺。

6.2 练习二:输出九九乘法表

这个就是上面嵌套循环那段的完整实践。我第一天写完还只是在IDEA里对着运行结果傻乐,第二天我把它升级成了函数封装的形式,虽然还没正式学方法,但先感受一下用一对大括号把代码包起来、通过参数传值的写法,算是给后面的"面向对象编程java"打了个预防针。

这里分享一个调式小技巧:如果乘法表输出成一整条长串不换行,检查一下内层循环用的是print还是println,以及外层循环末尾有没有加println()换行。新手Debug半天,最后往往发现只是这个两个打印方法的差别。

6.3 练习三:猜数字游戏

猜数字这个练习我强烈推荐,因为它把Day2的所有知识点串起来用了:变量存数据、Scanner读输入、Random生成随机数、while控制游戏循环、if判断大小、break跳出循环。整个程序50行左右,是一个"从语法到逻辑"的完整闭环。

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; // 生成1~100 Scanner sc = new Scanner(System.in); while (true) { System.out.print("请输入你的猜测(1-100):"); int guess = sc.nextInt(); if (guess > target) { System.out.println("猜大了!再试一次。"); } else if (guess < target) { System.out.println("猜小了!再试一次。"); } else { System.out.println("恭喜!猜中了!"); break; } } } }

random.nextInt(100) + 1这个写法值得讲一下:nextInt(100)生成的是0到99的整数,整体加上1,范围就变成了1到100。如果你想生成区间[m, n]的整数,通用写法就是random.nextInt(n - m + 1) + m。这个公式在以后很多场景都会碰到,值得记下来。

6.4 Day2的复盘:我踩过的坑清单

白天学完,我花了半小时把当天的问题列成一个清单,整理成自己的"Day2避坑手册":

  1. 环境变量PATH配置后没重新打开终端:导致javac找不到,以为是配置问题,其实只是终端没刷新。
  2. long和float的字面量不加后缀:导致编译报错或者数据失真,加L/F后缀要形成肌肉记忆。
  3. 强转double到int以为是四舍五入:实际是直接截断,(int) 3.99结果是3,不是4。
  4. "1" + 2 + 3结果不是6是"123":字符串一旦参与+运算,从+开始就变成拼接了。
  5. switch漏写break:导致case穿透,输出了一串意外内容。
  6. for循环变量定义错位置:变量定义在循环体内,导致每次循环都被重置。
  7. if条件顺序写反:让小范围条件先执行,大范围条件被"截胡",逻辑全乱。

这份清单最大的价值不是"知道了七个坑",而是让我开始建立自己的错误索引。后面每学一块新内容,我都会往这个清单里加东西,慢慢地它就成了我最私人的、网上都搜不到的"java基础知识总结"。我也建议大家从Day1开始就建立这样的清单,哪怕很零碎,过一个月回头看会发现它才是你进步最快的见证。

学完Day2,我的整体感觉是:语法说起来挺枯燥,但一旦你把每个知识点都用手指头敲进代码里,让程序按你的想法判断、循环、输出,那种"电脑在听我指挥"的感觉是看多少视频都换不来的。第二天虽然没写任何"高大上"的东西,但我已经能靠纯Java语法完成一个小游戏了,这种能力感是实打实的。如果你的Day2也卡在某个环节上,别怀疑自己,大概率只是缺一个"故意敲错、观察报错、再改回来"的循环而已。这个循环,本身就是典型的重试精神——跑几次,看结果,修正,再跑,直到跑通为止。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询