当前位置: 首页 > news >正文

JAVA重点基础、进阶知识及易错点总结(1)---数据类型、运算符、流程控制

🚀 Java 巩固进阶 · 第1天

主题:数据类型、运算符与流程控制 —— 避开那些“隐形”的坑

📅 进度概览:重启Java基础。
💡 核心价值:很多生产环境的Bug(如金额精度丢失、空指针崩溃、逻辑穿透)都源于对这些“简单”知识的误解。今天我们将深入底层,建立防御性编程思维。


一、基本数据类型与字面量规范

1. 八大基本类型全景图

分类类型字节范围/特点默认后缀
整数byte1-128 ~ 127-
short2-32,768 ~ 32,767-
int4最常用,约±21亿(默认)
long8超大整数L(推荐大写)
浮点float4单精度,易丢失精度f/F
double8默认小数类型,双精度(默认)
字符char2单字符,Unicode' '(单引号)
布尔boolean-true/false-

2. ⚠️ 字面量陷阱与规范

核心规则:编译器对数字字面量的“默认偏见”。

  • 整数默认是int:若赋值给long且超出int范围,必须加L
  • 小数默认是double:若赋值给float,必须加f,否则报错“可能损失精度”。
❌ 经典错误案例
// 1. 浮点赋值错误floatprice=9.9;// ❌ 编译报错:9.9是double,转float会丢精度// 2. 长整型溢出longbigNum=2147483648;// ❌ 编译报错:字面量被视为int,已超出int最大值
✅ 正确写法 & 最佳实践
// 1. 显式后缀floatprice=9.9f;// ✅ 推荐longbigNum=2147483648L;// ✅ 推荐:L必须大写!(小写l易混淆为1)// 2. 金融铁律:严禁使用 float/double 计算金额!// ❌ 错误:double money = 0.1 + 0.2; // 结果可能是 0.30000000000000004// ✅ 正确:使用 BigDecimalBigDecimalamount=newBigDecimal("0.1").add(newBigDecimal("0.2"));

二、浮点数精度陷阱:为什么0.1 + 0.2 != 0.3

1. 底层原理 (IEEE 754)

计算机使用二进制存储小数。十进制的0.1在二进制中是无限循环小数(0.00011001100...)。由于存储空间有限(float 32位/double 64位),必须进行截断,从而产生微小的精度误差。

2. 致命案例

doublea=0.1;doubleb=0.2;doublec=0.3;// ❌ 经典面试题:输出 falseSystem.out.println(a+b==c);// 真相:0.30000000000000004 != 0.3

3. 解决方案

  • 方案 A:误差范围比较 (科学计算)
    doubleepsilon=1e-6;// 允许的最大误差if(Math.abs((a+b)-c)<epsilon){System.out.println("视为相等");}
  • 方案 B:BigDecimal (金融/商业计算 - 唯一推荐)
    // ⚠️ 关键:构造函数必须传 String,不能传 double!BigDecimalbd1=newBigDecimal("0.1");BigDecimalbd2=newBigDecimal("0.2");if(bd1.add(bd2).equals(newBigDecimal("0.3"))){System.out.println("金额匹配");}

三、包装类、自动装箱与 Integer 缓存池

这是大厂面试最高频考点,也是生产环境 NPE (空指针) 的重灾区。

1. 核心机制

  • 自动装箱Integer i = 10;→\rightarrowInteger.valueOf(10)
  • 自动拆箱int n = i;→\rightarrowi.intValue()
  • Integer 缓存池 (Integer Cache)
    • JVM 为了优化性能,预先创建了-128 到 127之间的整数对象。
    • 在此范围内,valueOf()返回缓存对象(引用相同)。
    • 超出范围,每次new一个新对象(引用不同)。

2. ⚠️ 陷阱演示

Integera=127;Integerb=127;System.out.println(a==b);// ✅ true (指向同一个缓存对象)Integerc=128;Integerd=128;System.out.println(c==d);// ❌ false (两个不同的对象,地址不同)// ⚠️ 拆箱导致的 NPE (空指针异常)Integere=null;// 下面这行代码等价于 e.intValue(),直接崩!intf=e;// throws NullPointerException

3. 扩展知识 (面试加分项)

  • 为什么是 -128~127?对应byte的范围,覆盖了最常用的整数区间。
  • 其他缓存Boolean(TRUE/FALSE),Character(\u0000~\u007F),Long/Short(-128~127)。
  • 配置调整:可通过 JVM 参数-XX:AutoBoxCacheMax=<size>扩大 Integer 缓存上限。

4. 🛡️ 防御性编程:安全拆箱

数据库查询返回值常为null,直接拆箱极其危险。

publicclassSafeUnboxingDemo{publicvoidprocessScore(IntegerdbScore){// 【方案 A】传统三元运算符 (最快)intscoreA=(dbScore==null)?0:dbScore;// 【方案 B】Optional 链式调用 (优雅,适合复杂逻辑)intscoreB=Optional.ofNullable(dbScore).filter(s->s>=0)// 过滤负分.orElse(0);// 默认值// 【方案 C】严格模式 (数据异常直接阻断,防止脏数据扩散)intscoreC=Optional.ofNullable(dbScore).orElseThrow(()->newIllegalArgumentException("积分不能为空"));}}

💡 最佳实践:对象比较永远用.equals();拆箱前必判空;Optional主要用于局部变量处理,不建议作为实体类字段。


四、逻辑运算符:短路机制 (&&vs&)

1. 核心区别

运算符名称行为特征典型场景
&&短路与左假则右不执行判空保护(obj != null && obj.isValid())
&非短路/按位与左右都执行位运算、需要副作用执行的场景
**``**短路或
|非短路/按位或左右都执行位运算

2. ⚠️ 生死攸关的案例

Stringuser=null;// ✅ 安全:user != null 为 false,&& 短路,后面不执行,不会报 NPEif(user!=null&&user.length()>5){...}// ❌ 崩溃:& 强制执行右边,user.length() 抛出 NullPointerExceptionif(user!=null&user.length()>5){...}

3. 副作用陷阱

intx=0;// 使用 &&:条件为假,x++ 被跳过if(false&&(x++>0)){}System.out.println(x);// 输出 0// 使用 &:无论左边如何,x++ 都会执行if(false&(x++>0)){}System.out.println(x);// 输出 1

五、Switch 语句的进化史

1. 版本演进

  • JDK 1.4-:仅支持byte,short,char,int(及枚举)。
  • JDK 1.7+:支持String(底层通过hashCode()+equals()实现)。
  • JDK 14+ (现代语法)
    • 支持箭头语法->(无需break,天然防穿透)。
    • 支持Switch 表达式(可直接返回值)。
    • 支持多 Case 合并(case "A", "B" -> ...)。

2. 代码对比

🔴 传统写法 (JDK 8及以前) - 风险:忘记 break
Stringtype="A";intresult=0;switch(type){case"A":result=1;break;// ⚠️ 忘了写 break 会导致穿透到 case "B"case"B":result=2;break;default:result=0;}
🟢 现代写法 (JDK 14+) - 推荐
Stringtype="A";// 直接作为表达式返回值,无穿透风险,代码极简intresult=switch(type){case"A"->1;case"B"->2;case"C","D"->3;// 多值合并default->0;};// 甚至可以在块中执行复杂逻辑并使用 yield 返回Stringmessage=switch(type){case"A"->{System.out.println("Processing A...");yield"Type A Processed";}default->"Unknown Type";};

3. ⚠️ 特别警示

  • Null 值炸弹:Switch 的条件表达式绝不能为 null(无论是 String 还是 Enum),否则直接抛NullPointerException。务必先判空!
    // ❌ 危险switch(userType){...}// 若 userType 为 null,直接崩// ✅ 安全if(userType!=null){switch(userType){...}}

📝 第1天 · 核心自查清单

知识点💡 核心口诀☠️ 致命陷阱✅ 最佳实践
字面量整 int 小 double,长 L 浮 ffloat f = 3.14编译错金额用BigDecimal,Long 后缀用大写L
浮点比较二进制存不准,等于号别乱用0.1 + 0.2 == 0.3为 falseMath.abs(diff) < epsilonBigDecimal
Integer 缓存-128 到 127 是亲戚,之外是新欢new Integer(128) == new Integer(128)为 false对象比较永远用.equals()
空指针拆箱包装类可能是 nullInteger i = null; int n = i;崩了拆箱前判空,或用Optional处理
短路逻辑前假后不跑 (&&),前真后不跑 (ll)误用&导致 NPE 或多余计算判空链式调用首选&&
Switch1.7 起能转 String,14+ 箭头更香忘写break导致逻辑穿透;Null 值崩盘新版 JDK 优先使用->表达式;先判空再 switch

👉 今日作业

  1. 编写一个工具方法,接收两个Double类型的金额参数,使用BigDecimal进行加法运算并返回结果(需处理 null 值)。
  2. 尝试复现Integer缓存的边界测试(127 vs 128),并打印它们的hashCodeidentityHashCode(System.identityHashCode) 以观察区别。

掌握这些细节,不仅能帮你通过大厂面试的“基础题”拷打,更能避免生产环境中那些隐蔽且难以排查的 Bug。

http://www.jsqmd.com/news/540852/

相关文章:

  • 思岚S1雷达+Cartographer纯激光建图实战:室内外效果对比与关键参数调优心得
  • 手把手教你用4G Cat.1 bis开发智能硬件:从电路设计到低功耗优化的完整实战
  • 机床自动上下料机械手(solidworks+x_t)
  • OFA图像英文描述模型效果展示:COCO精简版在儿童绘本图、教育课件图的语义适配能力
  • BotW-Save-Manager终极方案:深度解析《塞尔达传说:旷野之息》跨平台存档迁移技术
  • 2026新托福备考APP哪家强?多次元托福凭32分型诊断断层领先 - 速递信息
  • C语言新手必练:10道经典算法题实战解析(附完整代码)
  • 主从博弈在共享储能与微网优化中的实战
  • N诺机试题
  • 面对运维效率低下与成本浪费,试试超自动化运维
  • 3步打造智能无人机:如何用ESP32开源飞控实现专业级飞行?
  • 终极美化指南:为Windows资源管理器添加惊艳毛玻璃效果
  • COA - CNN - BiGRU - Attention分类:新手友好的数据预测方案
  • 从Jupyter到PLC边缘设备:Python视觉模型部署全流程,含Docker+ONNX+RTSP低延迟优化
  • 代谢组+微生物组联合分析实战:从样本处理到生物标志物筛选的完整流程
  • IIS 10配置asp+access环境注意事项
  • 图床项目(二) 接口设计
  • 突破限制:BlenderCompat让Windows 7焕发新活力运行Blender 3.x
  • [USACO14MAR] Mooo Moo S
  • 视觉算法平台落地路径探索
  • Llama-3.2V-11B-cot入门必看:bf16精度下视觉嵌入层数值稳定性保障
  • 中医理疗培训师资靠谱吗?守嘉职业技能汇聚资深专家团队授课 - 品牌排行榜单
  • 从数据到战略:产品经理决策框架
  • 中医理疗能调理亚健康吗?守嘉职业技能课程直击亚健康痛点 - 品牌排行榜单
  • 首款支持AI渗透的WebShell管理工具,聊个天就能实现免杀|实现高隐蔽内网渗透
  • LTspice进阶技巧:用.step+.tf命令自动扫描三极管工作点(含Python数据处理)
  • 免费TXT文件合并工具、TXT合并工具
  • CCPD:如何让车牌识别在复杂场景下实现99%准确率?
  • Ollama + DeepSeek + 芋道框架 + SearXNG 本地联网搜索完整教程
  • 2026北京珠宝回收公司哪家专业?从鉴定到变现,资深用户总结的选型逻辑 - 速递信息