null是 Java 中表示引用类型变量不指向任何对象的特殊字面量。一、基本特性只能赋给引用类型对象、数组、String不能赋给基本类型类中未初始化的引用类型字段默认值为null可转型为任何引用类型(String) null二、常见错误NullPointerExceptionStringsnull;s.length();// ❌ NPE只要引用为null时调用.方法就会触发 NPE——Java 中最常见的运行时异常。三、安全处理 null 的 4 种方式// 1. 显式判空if(str!null)System.out.println(str.length());// 2. 三元运算符intlen(strnull)?0:str.length();// 3. Objects 工具类Java 7intlenObjects.requireNonNull(str,str 不能为 null).length();StringdefObjects.toString(str,默认值);// 4. OptionalJava 8intlenOptional.ofNullable(str).map(String::length).orElse(0);三、常见陷阱// 陷阱1equals() 调用顺序Stringsnull;s.equals(abc);// ❌ NPEabc.equals(s);// ✅ 推荐// 陷阱2包装类型自动拆箱Integernumnull;intnnum;// ❌ NPE// 陷阱3数组元素默认值String[]strsnewString[3];// 默认 nullstrs[0].length();// ❌ NPE四、实战排查案例多层嵌套对象的 NPE 排查假设有一个用户信息查询场景需要获取用户所在城市的名称代码中出现了多层链式调用publicclassUser{privateProfileprofile;publicProfilegetProfile(){returnprofile;}}publicclassProfile{privateAddressaddress;publicAddressgetAddress(){returnaddress;}}publicclassAddress{privateStringcity;publicStringgetCity(){returncity;}}publicclassUserService{publicStringgetUserCity(Useruser){// 问题代码多层链式调用任何一层为 null 都会触发 NPEreturnuser.getProfile().getAddress().getCity();}}排查思路定位异常栈从日志中捕获的异常栈可以看到NullPointerException发生在UserService.getUserCity()的第 3 行指向user.getProfile().getAddress().getCity()。逐层断点调试在调用链的每一层设置断点分别检查user、user.getProfile()、user.getProfile().getAddress()是否为null。日志输出辅助在调用前打印各层对象状态publicStringgetUserCity(Useruser){System.out.println(user user);if(user!null){System.out.println(profile user.getProfile());if(user.getProfile()!null){System.out.println(address user.getProfile().getAddress());}}returnuser.getProfile().getAddress().getCity();}假设日志输出为user com.example.User123456 profile null则说明user对象存在但其profile字段未初始化导致后续调用getAddress()时触发 NPE。防御性编程建议逐层判空最直接的方式在每一层调用前检查是否为nullpublicStringgetUserCity(Useruser){if(usernull)return未知城市;Profileprofileuser.getProfile();if(profilenull)return未知城市;Addressaddressprofile.getAddress();if(addressnull)return未知城市;returnaddress.getCity();}使用 OptionalJava 8publicStringgetUserCity(Useruser){returnOptional.ofNullable(user).map(User::getProfile).map(Profile::getAddress).map(Address::getCity).orElse(未知城市);}使用工具类方法如 Apache Commons Lang 的ObjectUtils.defaultIfNull或自定义工具类封装判空逻辑避免重复代码。设计层面预防在构造函数或工厂方法中确保Profile、Address等嵌套对象被正确初始化或使用构建器模式强制要求必要字段非空。五、小结要点说明本质引用不指向任何对象避免 NPE访问前判空多用Optional和Objects方法调用常量.equals(var)优于var.equals(常量)自动拆箱包装类型为null时赋值给基本类型会抛 NPE六、常见面试题1. 如何有效避免 NullPointerException防御性检查在访问对象方法或属性前显式判空if (obj ! null)。使用工具类Objects.requireNonNull()快速校验参数StringUtils.isEmpty()等工具方法简化判空。合理使用 Optional用Optional.ofNullable()包装可能为 null 的返回值配合orElse()/orElseGet()提供默认值。避免自动拆箱包装类型赋值给基本类型前确认非 null如Integer count null; int c count;会抛 NPE。2. Optional 是解决 NPE 的银弹吗不是。Optional主要用于返回值场景提醒调用者处理空值但不应滥用不应用于字段、方法参数或集合中。过度使用Optional.get()而不判isPresent()反而更危险。核心仍是培养编码习惯尽早校验、明确契约、善用工具类。3.判空与equals()判空有何区别用于判断引用是否为null是安全的不会抛 NPE。equals()是实例方法若调用对象为null会直接抛 NPE因此推荐用常量.equals(var)或Objects.equals(var1, var2)来避免。