判断字符串是否为空需先判null再判空串,推荐str != null && !str.isEmpty();null与""语义不同,不可混用,数据库、JSON等场景须分别处理。

判断字符串是否为空时,equals("") 会崩给 null
空字符串 "" 是对象,null 是“没对象”。对 null 调用任何方法(包括 equals)都会直接抛出 NullPointerException。
- 常见错误现象:
str.equals("")在str == null时崩溃,日志里只看到Exception in thread "main" java.lang.NullPointerException - 正确做法:必须先判
null,再判内容,顺序不能反 ——str != null && str.equals("") - 更推荐用
str != null && str.isEmpty():语义更清晰,且isEmpty()是 JDK 6+ 的标准 API,比equals("")少一次字符串常量池查找 - 别偷懒写成
"".equals(str):虽然能防 NPE,但可读性差,团队协作中容易被误读为“把空串当主语”,不建议作为默认习惯
== 比较 "" 和 null 的结果永远是 false
== 比的是引用地址。"" 指向字符串常量池里的一个真实对象;null 根本没有地址。两者不可能相等,也不该混用。
- 典型陷阱:
if (str == "")看似省事,但只对字面量""可靠;若str = new String(""),==就返回false,逻辑就漏了 -
str == null是唯一安全、明确、低成本的空引用判断方式,不要试图用str.equals(null)—— 这本身就会触发 NPE - 数据库映射场景中,JDBC 返回的字段可能是
null(未填写),也可能是""(显式提交了空值),二者业务含义不同,==判定毫无意义,必须分开处理
初始化和默认值:成员变量 vs 局部变量行为完全不同
Java 对不同作用域的变量赋予了不同的默认值,这个差异直接影响你是否需要手动初始化。
- 类成员变量(field):
String s;默认就是null,不用赋值也会有值;但局部变量(method 内)String s;不赋值就用,编译直接报错variable s might not have been initialized - 显式写
String s = "";是初始化为有效对象,后续可放心调用length()、trim()等;而String s = null;是主动声明“此处暂无值”,适合延迟加载或条件分支中的占位 - 用 Lombok 的
@Data或 Jackson 反序列化时,JSON 中缺失字段 → 字段为null;JSON 中字段为"name": ""→ 字段为""。别指望框架自动帮你转成统一形式
实际校验逻辑:怎么写才既安全又不易漏
生产环境里,一个字符串要“真正可用”,得同时过两关:不是 null,也不是空串。漏掉任一检查都可能引发下游异常或脏数据。
立即学习“Java免费学习笔记(深入)”;
- 最简健壮写法:
if (str != null && !str.isEmpty())—— 两步合并一行,短路求值保证安全 - 如果还要忽略纯空白(如
"\t \n"),用str != null && !str.trim().isEmpty();注意trim()对null仍会 NPE,所以null检查必须在前 - Apache Commons Lang 提供
StringUtils.isNotBlank(str),内部已封装好上述逻辑,但引入第三方包前请确认项目规范允许 - 别用
str.length() == 0单独判断空串:它比isEmpty()多一次 int 计算,语义也弱;更关键的是,有人会误写成str != null || str.length() == 0(用错了逻辑符),这种 bug 很难一眼发现
Objects.equals(a, b) 虽然能防 NPE,但它把 null 和 "" 当作不同值处理 —— 这恰恰是对的,因为它们本来业务语义就不同。










