定位:本体系文档从 Java 语言设计哲学、表达式语义、类型系统、数值模型、对象模型、异常模型、控制流模型等核心机制入手,构建一套面向高级工程师、架构师的语言认知框架。 目标:从语言本质与原理视角解释常见 Bug、陷阱、谜题产生的原因,并形成长期可复用的 Java 思维模型。
Java 的语言机制深受三大高度稳定哲学影响:
Java 大部分原始类型(int、byte、float 等)全部基于固定长度存储,意味着:
Java 在追求安全的同时又必须保持向后兼容,因此:
许多“谜题”来自于:
本章揭示 Java 数值相关陷阱背后的底层规律。
Java 的 % 运算遵循 向零取整的除法模型,其符号由左操作数决定。
-1 % 2 == -1
不要用 x % 2 == 1 判断奇数,应使用:
(x & 1) != 0
或
x % 2 != 0
Java 中所有浮点计算均基于 IEEE754 二进制浮点表示。
2.0 - 1.1 != 0.9
整数字面量表达式默认以 int 计算,只有出现 long 字面量时才按 long 计算。
long a = 24*60*60*1000*1000; // 溢出
解决方式:
long a = 24L*60*60*1000*1000;
表达式类型由“最窄的容器”决定,而不是左侧变量决定。
+= 等复合赋值会自动隐式转换为目标类型。
short x = 0;
x += 123456; // silent truncation
规律:
所有小于 int 的类型在表达式中都会自动提升为 int。
这一部分解释所有“看不见”的类型推断规则。
(int)(char)(byte)-1 == 65535
原因在于:
规律:
跨符号 → 无符号 → 符号的链式转换会产生意料之外的巨大数值。
逻辑:
典型现象:
true ? 'X' : 0 // 'X'
true ? 'X' : i // int 88
规律:
if-else 的行为与三元表达式不同,后者严格遵守类型提升规则。
Java 通过缓存加速小整数:
[-128, 127] 使用缓存对象
典型现象:
Integer a = 100, b = 100; // true
Integer c = 150, d = 150; // false
规律:
所有包装类型做 == 比较都是潜在 Bug。
这里总结 Java 字符串中的根本陷阱: 编译期处理、Unicode 处理、编码处理、正则处理不属于同一层级。
典型现象:
F:\user\data
因 \u 会被认为是 Unicode 起始符,导致编译失败。
规律:
任何包含
\u的文本,都必须转义为\\u。
new String(byteArray)
在不同平台会出现不同结果,因为依赖平台默认编码。
规律:
永远使用带 charset 的构造方法。
"."
→ 匹配所有字符
规律:
涉及文件路径、包名替换等需求时首选
replace而不是replaceAll。
循环相关陷阱均来自:
for (int i = 0; i <= Integer.MAX_VALUE; i++);
因为 MAX_VALUE + 1 → MIN_VALUE → 循环永远成立。
规律:
循环边界应使用 long。
float f = Integer.MAX_VALUE;
f + 50 == f
规律:
避免使用 float/double 作为循环变量。
规律:
移位量必须为常量。
Integer i = 129;
while (i<=j && j<=i && j!=i);
规律:
循环中任何包装类型比较都可能是非常危险的信号。
Java 的异常设计具备三个核心原则:
以下情况 finally 不执行:
典型例子:
try {
System.exit(0);
} finally {
// 不会执行
}
多接口继承时,抛出异常是父接口声明异常的交集。
旧写法:
in1.close() throws → in2 永远无法关闭
规律:
任何涉及资源的代码都应使用 TWR。
Duck d = new RepeatDuck();
d.fly(); // 调用父类方法
规律:
静态方法绑定在类,而非对象。
典型例子:
private static final Main instance = new Main();
private static final long i = System.currentTimeMillis();
此时 i 尚未初始化 → instance 中读到 0。
规律:
禁止在静态字段中构造自身实例。
class Object {
private Object obj = new Object(); // 无限递归
}
规律:
不要在字段初始化中直接构造自身类型。
本章汇总所有谜题背后蕴含的普适性原理,可作为编码规范或语言思维准则。
原文中的谜题来自于 Java 的语言机制本身,而非开发者的疏忽。 本体系文档试图将这些隐藏行为提升为:
本质上:
掌握 Java 谜题,就是掌握 Java 语言运行模型的边界与极限。