null不是对象而是引用类型的特殊字面量,表示不指向任何实例;它无类型、无内存地址、无法调用实例方法,仅能用==和!=安全比较;空对象模式通过提供默认行为的实现类来消除裸null,强调语义化建模而非单纯避错。

Java 中的 null 不是“空对象”,它根本就不是对象——它是引用类型的特殊字面量,表示“当前不指向任何对象实例”。
为什么 null 不能调用方法?
因为 null 没有类型、没有内存地址、没有字段也没有方法表。当你写 obj.toString() 而 obj == null 时,JVM 在运行期发现操作数栈顶是 null,直接抛出 NullPointerException,连虚方法分派都走不到。
- 它不是
Object的子类,也不是任何类的实例:null instanceof Object永远返回false -
==和!=是唯一能安全比较null的运算符;.equals()、.hashCode()等一切实例方法调用都会崩 - 静态方法不受影响(如
String.valueOf(null)是合法的),因为不依赖实例
null 和空对象模式(Null Object Pattern)别混了
有人把“空对象模式”误解成“创建一个叫 NullObject 的实例来代表 null”,其实完全相反:这个模式的目标就是消灭裸 null。
- 它要求你定义统一接口(如
PaymentProcessor),再提供两个实现:RealPaymentProcessor和NullPaymentProcessor - 后者所有方法体为空或返回默认值(如
process() { return false; }),且isNil() { return true; } - 关键在工厂或服务层:当查不到真实支付处理器时,不返回
null,而是返回new NullPaymentProcessor() - 这样调用方永远不用写
if (processor != null) processor.process()
什么时候该用 Optional,什么时候该用空对象模式?
Optional 是为返回值场景设计的临时容器,强调“这个值可能不存在”;空对象模式是为长期协作对象设计的契约替代,强调“它总是存在,只是行为不同”。
立即学习“Java免费学习笔记(深入)”;
- 用
Optional:查询数据库用户,没查到就返回Optional.empty()—— 调用方必须显式处理“无用户”分支 - 用
NullUser:系统里每个订单都必须关联一个User接口,但匿名订单允许“虚拟用户”,这时NullUser可返回"anonymous"作为getName()结果,且不会中断后续计费、日志等流程 - 误用风险:
Optional被当成普通字段存进实体类、或用于方法参数,反而增加调用负担;空对象被滥用在简单 DTO 或配置对象上,纯属过度设计
真正容易被忽略的是:空对象模式的价值不在“避免 NPE”,而在于把“空”的语义显式建模进领域模型——比如 NullShippingMethod 表示“无需物流”,比 shippingMethod == null 更贴近业务语言。一旦你开始思考“这个空,到底想表达什么业务含义”,才算是用对了。










