Java中没有“空对象”概念,只有null表示引用未指向任何对象;""是真实存在的空字符串实例,二者状态不同必须分开判断,混用会导致NPE或逻辑错误。

空对象不是Java语言概念,null才是
Java里没有“空对象”这个语法或运行时概念——只有 null 关键字,表示一个引用不指向任何堆内存中的实例。所谓“空对象”,其实是开发者对某些特殊对象(如空集合、空字符串、自定义的空哨兵对象)的口语化误称,容易引发误解。
例如:String s = "" 创建的是一个真实存在的 String 实例,它在字符串常量池中有地址,能安全调用 equals()、length();而 String s = null 的 s 根本没指向任何对象,调用任何方法都会抛 NullPointerException。
为什么 String == "" 和 s == null 必须分开判断
因为它们代表完全不同的状态:一个是“有对象但内容为空”,一个是“连对象都没有”。混用会导致逻辑漏洞或崩溃。
-
s == null检查的是引用是否为空(栈中值是否为null),只能用==,不能用equals() -
s.equals("")前必须确保s != null,否则直接 NPE;更安全写法是"".equals(s)(把字面量放前面) - 如果业务上“未设置”和“明确设为空”需区分(比如表单提交),
null适合表达“未填写”,""适合表达“填了但留空”
常见踩坑场景:集合、Optional、JSON反序列化
这些地方最容易混淆“不存在”和“存在但为空”:
立即学习“Java免费学习笔记(深入)”;
-
Listvslist = null List:前者调用list = new ArrayList() list.size()报错;后者返回0,可安全遍历 - 用
Optional.of(null)会立即抛NullPointerException;正确姿势是Optional.ofNullable(s) - FastJSON / Jackson 反序列化时,默认把 JSON 中缺失字段设为
null,而空字符串字段设为""——若代码只判"".equals(s),会漏掉null分支
自定义“空对象”模式要谨慎
比如写一个 EmptyUser.getInstance() 来替代 null,这属于 Null Object Pattern,能避免 NPE,但代价是:增加类复杂度、掩盖真实缺失状态、可能让调用方误以为“数据存在”。
除非团队明确约定且所有上下游都遵守该契约,否则优先用 null 表达“无”,用空集合/空字符串表达“有但空”。Java 8+ 更推荐用 Optional 显式封装可能为空的返回值。
最易被忽略的一点:null 是 JVM 级别的底层语义,而“空对象”全是应用层模拟——只要没彻底消灭 null 的传播路径(比如参数校验、DTO 转 VO 时未做映射),就永远存在隐式空指针风险。











