一、Java 体系结构(JDK/JRE/JVM)
1.核心组件对比
| 组件 | 全称 | 包含内容 | 用途 | 特点 |
|---|---|---|---|---|
| JDK | Java Development Kit | JRE + 开发工具(javac、jdb、jar等) | 开发Java程序 | 包含编译器等开发工具 |
| JRE | Java Runtime Environment | JVM + 标准类库(java.lang、java.util等) | 运行Java程序 | 用户只需运行程序时安装 |
| JVM | Java Virtual Machine | 字节码解释器、JIT编译器、内存管理等 | 执行字节码 | 平台相关,字节码平台无关 |
2.层级关系
JDK (开发工具包) ├── JRE (运行环境) │ ├── JVM (虚拟机) │ └── 标准类库 (API) ├── 编译器 (javac) ├── 调试器 (jdb) └── 打包工具 (jar)
3.跨平台原理
核心机制:字节码 + 平台特定的JVM
编译时:
.java→.class(字节码,平台无关)运行时:JVM加载并执行字节码(JVM本身平台相关)
口号:一次编写,到处运行
4.关键要点
- javac编译器只在JDK中
- JRE不包含任何开发工具(javac、jdb等)
- 安装JDK后无需单独安装JRE(JDK已包含JRE)
- JVM执行流程:加载 → 验证 → 解释/编译(JIT)→ 执行
- JIT编译器:将热点字节码编译为本地机器码,提升性能
1.基本数据类型(8种)
| 类型 | 关键字 | 大小 | 默认值 | 备注 |
|---|---|---|---|---|
| 整数 | byte | 1字节 | 0 | 最节省内存 |
| short | 2字节 | 0 | ||
| int | 4字节 | 0 | 默认整数类型 | |
| long | 8字节 | 0L | 字面量加L后缀 | |
| 浮点 | float | 4字节 | 0.0f | 单精度,需f后缀 |
| double | 8字节 | 0.0d | 默认浮点类型 | |
| 字符 | char | 2字节 | '\u0000' | 单引号,Unicode字符 |
| 布尔 | boolean | 1位 | false | 不与整数互换 |
2.引用数据类型
类(如String、自定义类)
接口
数组
枚举
3.重要特性对比
| 特性 | 基本数据类型 | 引用数据类型 |
|---|---|---|
| 存储内容 | 实际值 | 对象内存地址 |
| 内存位置 | 栈 | 堆(对象在堆,引用在栈) |
| 默认值 | 有(如0、false) | null |
| 可为null | 否 | 是 |
| 调用方法 | 不能直接调用(通过包装类) | 可以调用 |
| 赋值方式 | 值拷贝 | 引用拷贝(共享对象) |
4.使用注意事项
- 内存优化:根据范围选择合适类型(如byte代替int)
- 精度问题:浮点数有舍入误差,金融计算用BigDecimal
- char类型:16位Unicode,可存储中文等特殊字符
- boolean:只有true/false
- 默认浮点:字面量
3.14默认是double,float需加f
三、Java 变量
1.变量三要素
数据类型:决定内存大小和操作方式
变量名:标识符,用于引用变量
值:存储在变量中的数据
2.命名规则
合法字符:字母、数字、下划线
_、美元符$首字符:不能是数字
不能是关键字:如
int、class、true等长度限制:理论上无限制,但应保持合理
3.命名规范(最佳实践)
camelCase:首字母小写,后续单词首字母大写(
userName、totalAmount)有意义:避免单字母(除循环变量)或模糊名称
布尔变量:以
is、has、can开头(isValid、hasPermission)常量:全大写,下划线分隔(
MAX_SIZE)避免:使用
_开头(有特殊含义)、拼音、缩写不清
4.变量初始化
| 变量类型 | 默认值 | 必须显式初始化 | 示例 |
|---|---|---|---|
| 成员变量 | 有 | 否 | int count;(默认0) |
| 静态变量 | 有 | 否 | static double price; |
| 局部变量 | 无 | 是 | int x = 10;(必须赋值) |
| 参数变量 | 由调用者提供 | 是 | void method(int param) |
5.常见错误
使用未初始化的局部变量
变量名以数字开头(
int 1stNum;)使用关键字作为变量名(
int class;)类型不匹配的赋值
四、Java 运算符
1.算术运算符
2.关系运算符
注意:==比较基本类型的值,比较对象的引用地址(非内容)
3.逻辑运算符
| 运算符 | 描述 | 短路特性 |
|---|---|---|
&& | 逻辑与 | 有(左false则短路) |
|| | 逻辑或 | 有(左true则短路) |
! | 逻辑非 | 无(一元运算符) |
& | 按位与/非短路与 | 无 |
| | 按位或/非短路或 | 无 |
短路特性优势:避免不必要的计算和异常(如空指针)
4.赋值运算符
5.三元运算符
语法:
条件 ? 表达式1 : 表达式2作用:简化if-else赋值逻辑
示例:
int max = (a > b) ? a : b;限制:表达式1和2类型需兼容,不能替代复杂逻辑
6.运算符优先级
()括号++--自增自减*/%乘除取模+-加减><>=<===!=关系&&||逻辑?:三元=+=-=等赋值
建议:不确定时使用括号明确优先级
7.特殊运算示例
java
// 浮点数除以0 double d = 5.0 / 0; // Infinity,不抛异常 // 自增区别 int x = 5; int a = x++; // a=5, x=6(后置:先使用后加) int b = ++x; // b=7, x=7(前置:先加后使用) // 复杂表达式 int x = 7; System.out.println(x++ + ++x); // 7 + 9 = 16
五、Docker Compose 回顾(关联题)
1.核心概念
用途:多容器应用的一键编排与管理
文件:
docker-compose.yml命令:
docker-compose up -d(后台启动)
2.关键配置
环境变量:
env_file字段加载.env文件(最佳实践)端口映射:
ports字段数据卷:
volumes字段(命名卷或绑定挂载)依赖:
depends_on(仅控制启动顺序,不等待就绪)
3.网络特性
默认:所有服务加入同一内部网络
服务发现:通过服务名直接访问(DNS解析)
多网络:一个服务可连接多个网络
4.常用命令
bash
docker-compose up -d # 后台启动 docker-compose down # 停止并移除容器、网络 docker-compose down -v # 同时删除命名卷 docker-compose logs # 查看日志 docker-compose exec # 进入容器 docker-compose config # 验证配置
5.适用场景
✅ 本地开发多服务应用
✅ CI/CD集成测试环境
✅ 单机部署微服务原型
❌ 大规模生产集群(用Kubernetes)
6.最佳实践
敏感信息用
.env文件管理,并加入.gitignore为不同环境准备不同
.env文件避免硬编码密码在yml文件中
六、易错点与综合总结
1.Java体系结构
javac只在JDK中,JRE只能运行不能编译
JVM平台相关,字节码平台无关
跨平台依赖各平台的JVM实现
2.数据类型
boolean只有true/false,不是0/1
整数除法截断小数部分
浮点数默认double,float需加
fchar是16位Unicode,可存中文
基本类型不能为null,引用类型默认null
3.变量
局部变量必须显式初始化
变量名不能以数字开头
不能用关键字命名
成员变量有默认值,局部变量没有
4.运算符
==比较对象时比地址不是内容&&和||有短路特性
5.综合示例
java
// 运算注意 double result = 10 / 3; // 错误:result=3.0(整数除法) double correct = 10.0 / 3; // 正确:result=3.333... // 三元运算符简化 int max = (a > b) ? a : b;
002-Java
一、循环结构基础
1.三种基本循环对比
| 循环类型 | 特点 | 适用场景 | 控制类型 |
|---|---|---|---|
| for循环 | 已知循环次数,三段式(初始化;条件;更新) | 明确迭代次数、遍历数组/集合 | 入口控制 |
| while循环 | 先判断条件,再执行循环体 | 循环次数不确定,条件判断前置 | 入口控制 |
| do-while循环 | 先执行一次循环体,再判断条件 | 至少执行一次,条件判断后置 | 出口控制 |
2.循环控制要点
入口控制:for、while(先判断条件,可能一次都不执行)
出口控制:do-while(至少执行一次)
共同点:for和while都是入口控制循环
二、跳转语句详解
1.三种跳转语句对比
| 语句 | 作用范围 | 功能 | 注意 |
|---|---|---|---|
| break | 循环结构、switch语句 | 跳出当前循环或switch,执行后续代码 | 不能用于普通if语句 |
| continue | 仅循环结构(for/while/do-while) | 跳过本次循环剩余代码,进入下一次迭代 | 不跳出循环,只跳过本次迭代 |
| return | 方法内部 | 结束当前方法,返回调用者 | 可用于void方法提前结束 |
2.break 语句
功能:立即终止最近的循环或switch结构
使用场景:
循环中找到目标后提前退出
switch中匹配到case后跳出
限制:不能用于普通if条件语句
示例:
for (int i = 0; i < 10; i++) { if (i == 5) { break; // 跳出循环,i=5时停止 } System.out.println(i); }
3.continue 语句
功能:跳过当前循环迭代的剩余部分,进入下一次循环
执行流程:
for循环:跳过循环体剩余代码 → 执行更新表达式(i++)→ 判断条件
while/do-while:跳过循环体剩余代码 → 直接判断条件
使用场景:
跳过数组中的无效元素
避免深层嵌套if,提高可读性
过滤特定条件的数据
示例:
for (int i = 0; i < 10; i++) { if (i % 2 == 0) { continue; // 跳过偶数 } System.out.println(i); // 只打印奇数 }
4.return 语句
功能:结束当前方法的执行,返回调用者
两种形式:
return; // void方法,无返回值 return value; // 非void方法,必须返回匹配类型的值
与break的区别:
return:结束整个方法break:只结束当前循环或switch
注意:return后的代码会导致"不可达代码"编译错误
5.System.exit(0)
功能:终止整个JVM进程
作用:结束所有方法的执行
参数:0表示正常退出,非0表示异常退出
三、条件判断结构
1.if-else 语句
基本语法:
if (条件) { // 条件为true时执行 } else if (条件2) { // 条件2为true时执行 } else { // 以上条件都不满足时执行 }省略大括号规则:
只有紧随if/else后的第一行代码属于条件块
后续代码无论缩进如何,都不属于条件块
示例:
if (x > 0) System.out.println("正数"); // 属于if块 System.out.println("这行总是执行"); // 不属于if块,总是执行
2.三元运算符 (?:)
语法:
条件 ? 表达式1 : 表达式2功能:简化if-else赋值逻辑
适用场景:
简单的变量赋值
方法返回值
参数传递
不适用场景:
多重条件嵌套
需要执行多个语句的分支逻辑
复杂的业务逻辑
示例:
int max = (a > b) ? a : b; // 代替if-else赋值
3.switch-case 语句
支持的数据类型:
基本整型:byte、short、int、char
包装类:Byte、Short、Integer、Character
字符串:String(JDK7+)
枚举:enum
不支持的类型:boolean、double、float等
特点:
支持多个离散值匹配
JVM可优化为跳转表(tableswitch/lookupswitch),性能可能优于多重if-else
需要break防止case穿透
示例:
switch (day) { case 1: System.out.println("周一"); break; case 2: System.out.println("周二"); break; default: System.out.println("其他"); }
4.if-else vs switch-case 选择
| 特性 | IF-ELSE | SWITCH-CASE |
|---|---|---|
| 条件类型 | 任意布尔表达式 | 等值比较(==) |
| 可读性 | 复杂条件时清晰 | 多个离散值时更清晰 |
| 性能 | 逐条件判断 | JVM可能优化为跳转表 |
| 适用场景 | 范围判断、复杂逻辑 | 枚举值、多个固定值匹配 |
四、常见错误与陷阱
1.循环常见错误
| 错误类型 | 描述 | 示例/避免方法 |
|---|---|---|
| 无限循环 | 条件永远为true,循环永不结束 | 确保条件能变为false,检查更新逻辑 |
| 边界错误 | 循环次数多一次或少一次 | 注意i < nvsi <= n,理解半开区间 |
| 修改控制变量 | 循环体内修改循环控制变量 | 避免在循环体内修改i等控制变量 |
| 空循环体 | 循环体为空,可能无意中省略 | 使用{}明确循环体范围 |
2.条件判断常见错误
省略大括号误解:认为所有缩进代码都属于条件块
switch-case穿透:忘记break导致多个case执行
浮点数相等比较:使用
==比较浮点数(应使用范围比较)空指针异常:条件判断中的对象可能为null
3.跳转语句错误
break误用:在if语句中使用break(应只在循环/switch中使用)
continue误解:认为continue会跳出循环(实际只跳过本次迭代)
不可达代码:return/break/continue后的代码无法执行
4.边界错误详解
半开区间:
for (int i = 0; i < n; i++)→ 执行n次(0到n-1)闭区间:
for (int i = 0; i <= n; i++)→ 执行n+1次(0到n)经典错误:
// 期望打印0-9,实际打印0-10 for (int i = 0; i <= 10; i++) { System.out.println(i); }
五、最佳实践与使用场景
1.循环选择指南
| 场景 | 推荐循环 | 原因 |
|---|---|---|
| 已知迭代次数 | for循环 | 结构清晰,控制集中 |
| 条件判断前置 | while循环 | 先判断后执行,安全 |
| 至少执行一次 | do-while循环 | 保证首次执行 |
| 遍历集合/数组 | 增强型for | 简洁,无需索引 |
2.跳转语句使用场景
使用break:
搜索找到目标后立即退出
错误发生时跳出循环
switch中匹配到case后终止
使用continue:
过滤无效数据
跳过特定条件的处理
简化嵌套if结构
使用return:
方法完成时正常返回
错误发生时提前返回
递归的终止条件
3.代码可读性优化
避免深层嵌套:使用continue提前返回,减少if嵌套
明确循环意图:选择最适合的循环类型
添加注释:复杂循环逻辑添加说明
提取方法:过长的循环体提取为独立方法
六、综合示例与练习
1.综合示例
// 使用break提前退出 int[] numbers = {1, 2, 3, 4, 5}; int target = 3; boolean found = false; for (int num : numbers) { if (num == target) { found = true; break; // 找到后立即退出 } } // 使用continue跳过特定元素 for (int i = 1; i <= 10; i++) { if (i % 2 == 0) { continue; // 跳过偶数 } System.out.println("奇数: " + i); } // 三元运算符简化 int score = 85; String grade = (score >= 90) ? "A" : (score >= 80) ? "B" : (score >= 70) ? "C" : "D"; // switch-case处理多个固定值 String day = "MON"; switch (day) { case "MON": case "TUE": case "WED": case "THU": case "FRI": System.out.println("工作日"); break; case "SAT": case "SUN": System.out.println("周末"); break; default: System.out.println("无效输入"); }2.常见陷阱练习
// 陷阱1:省略大括号的误解 int x = 5; if (x > 0) System.out.println("正数"); System.out.println("这行总是执行"); // 不属于if块! // 陷阱2:switch-case穿透 int option = 1; switch (option) { case 1: System.out.println("选项1"); // 缺少break,会继续执行case 2 case 2: System.out.println("选项2"); break; } // 输出:选项1 选项2 // 陷阱3:浮点数比较 double a = 0.1 + 0.2; double b = 0.3; if (a == b) { // false!浮点数精度问题 System.out.println("相等"); }七、易错点总结
1.语法细节
if省略大括号:只控制第一行代码
switch支持类型:不支持boolean、double、float
三元运算符:只适合简单赋值,不能替代复杂if-else
do-while:末尾有分号
while(条件);
2.逻辑理解
break vs continue:
break:跳出循环,执行循环后代码
continue:跳过本次,继续下一次循环
入口 vs 出口控制:
入口:可能一次都不执行(for、while)
出口:至少执行一次(do-while)
边界条件:
i < n:n次循环(0到n-1)i <= n:n+1次循环(0到n)
3.性能与优化
switch优化:JVM可能优化为跳转表,多分支时效率高
循环效率:避免在循环内创建对象、进行复杂计算
提前退出:找到目标后及时break,避免无效循环