Java 注解@NotNull 和 @NotEmpty區(qū)別深度解析
要理解這兩個(gè) Java 注解的核心區(qū)別與應(yīng)用場(chǎng)景,需從定義來(lái)源、校驗(yàn)邏輯、適用類型三個(gè)維度展開(kāi)分析,以下是詳細(xì)解讀:
一、核心信息概覽
首先明確兩個(gè)注解的基礎(chǔ)定位,避免混淆:
對(duì)比維度 | javax.validation.constraints.NotNull | org.hibernate.validator.constraints.NotEmpty |
所屬框架 | JSR 380 標(biāo)準(zhǔn)(Java Validation API) | Hibernate Validator 擴(kuò)展(標(biāo)準(zhǔn)的實(shí)現(xiàn)之一) |
核心作用 | 禁止值為 null | 禁止值為 null 且 禁止 “空內(nèi)容”(如空字符串、空集合) |
依賴關(guān)系 | 標(biāo)準(zhǔn)注解,所有 Validation 實(shí)現(xiàn)都支持 | 需額外引入 Hibernate Validator 依賴 |
二、關(guān)鍵差異深度解析
1. 校驗(yàn)邏輯:“單一禁止” vs “雙重禁止”
這是兩者最核心的區(qū)別,直接決定了校驗(yàn)范圍:
- @NotNull:僅校驗(yàn) “是否為 null”
只判斷值是否為 null,不關(guān)心非 null 值的 “內(nèi)容是否為空”。
示例(非 null 但 “空內(nèi)容” 的情況,@NotNull 會(huì)判定為有效):
public class User {
// 允許:值為""(空字符串)、[](空集合)、new Object()(非null對(duì)象)
@NotNull
private String username = "";
@NotNull
private List<String> tags = new ArrayList<>(); // 空集合也會(huì)通過(guò)校驗(yàn)
}- @NotEmpty:校驗(yàn) “非 null + 非空內(nèi)容”
是 @NotNull 的增強(qiáng)版,同時(shí)滿足兩個(gè)條件才判定為有效:
public class User {
// 無(wú)效:值為null(違反@NotNull)
@NotEmpty
private String username = null;
// 無(wú)效:值為""(非null,但空字符串,違反@Size(min=1))
@NotEmpty
private String email = "";
// 無(wú)效:值為new ArrayList<>()(非null,但空集合,違反@Size(min=1))
@NotEmpty
private List<String> tags = new ArrayList<>();
}本質(zhì)上,@NotEmpty 的校驗(yàn)邏輯是通過(guò)組合注解實(shí)現(xiàn)的(從源碼可見(jiàn)):
// @NotEmpty 源碼中組合了 @NotNull 和 @Size(min=1)
@NotNull // 保證非null
@Size(min = 1) // 保證內(nèi)容長(zhǎng)度/大小 ≥1(空內(nèi)容會(huì)觸發(fā)此注解的校驗(yàn)失敗)
public @interface NotEmpty { ... }- 值不能為 null;
- 值的 “內(nèi)容” 不能為空(具體 “空內(nèi)容” 的定義隨類型變化)。
示例(@NotEmpty 判定為無(wú)效的情況):
2. 適用數(shù)據(jù)類型:“通用” vs “限定內(nèi)容型”
兩者適用的字段類型不同,@NotEmpty 僅支持 “有內(nèi)容長(zhǎng)度 / 大小” 的類型:
數(shù)據(jù)類型 | @NotNull 是否適用 | @NotEmpty 是否適用 | 說(shuō)明(@NotEmpty 的 “空內(nèi)容” 定義) |
基本類型包裝類 | 是(如 Integer) | 否(無(wú) “內(nèi)容” 概念) | 如 Integer age = null:@NotNull 校驗(yàn),@NotEmpty 不支持 |
String | 是 | 是 | “空內(nèi)容”= 長(zhǎng)度為 0 的字符串("") |
集合 / 數(shù)組(如 List、Set、int []) | 是 | 是 | “空內(nèi)容”= 長(zhǎng)度 / 大小為 0(如 new ArrayList<>()、new int[0]) |
Map | 是 | 是 | “空內(nèi)容”= 鍵值對(duì)數(shù)量為 0(new HashMap<>()) |
自定義對(duì)象 | 是(如 User) | 否(無(wú) “內(nèi)容” 概念) | 僅需判斷對(duì)象是否為 null,用 @NotNull 即可 |
3. 依賴與兼容性:“標(biāo)準(zhǔn)” vs “擴(kuò)展”
- @NotNull:無(wú)額外依賴
屬于 JSR 380 標(biāo)準(zhǔn)注解(包路徑為 javax.validation.constraints),只要項(xiàng)目引入了任何符合標(biāo)準(zhǔn)的 Validation 實(shí)現(xiàn)(如 Hibernate Validator、Apache BVal),就能直接使用,兼容性強(qiáng)。
- @NotEmpty:需依賴 Hibernate Validator
是 Hibernate Validator 提供的擴(kuò)展注解(包路徑為 org.hibernate.validator.constraints),并非標(biāo)準(zhǔn) API。若項(xiàng)目未引入 Hibernate Validator(僅用標(biāo)準(zhǔn) API 或其他實(shí)現(xiàn)),使用此注解會(huì)報(bào) “找不到注解” 錯(cuò)誤。
Maven 依賴示例(需手動(dòng)引入):
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>8.0.1.Final</version> <!-- 版本需與項(xiàng)目兼容 --> </dependency>
三、使用場(chǎng)景選擇建議
根據(jù)業(yè)務(wù)需求選擇注解,避免 “過(guò)度校驗(yàn)” 或 “校驗(yàn)不足”:
業(yè)務(wù)需求 | 推薦注解 | 示例場(chǎng)景 |
僅需確保值 “存在”(非 null),不關(guān)心內(nèi)容 | @NotNull | 1. 年齡(Integer age,允許 0 但不允許 null);2. 自定義對(duì)象(User user,只要對(duì)象非 null 即可) |
需確保值 “存在且有意義”(非 null + 非空內(nèi)容) | @NotEmpty | 1. 用戶名(String username,不允許 null 或 “”);2. 用戶標(biāo)簽(List<String> tags,不允許 null 或空集合);3. 地址(String address,不允許 null 或空字符串) |
四、常見(jiàn)誤區(qū)提醒
- 誤區(qū) 1:@NotNull 能校驗(yàn)空字符串 / 空集合
錯(cuò)誤!@NotNull 只管 “是否為 null”,空字符串("")、空集合(new ArrayList<>())都是非 null 值,會(huì)通過(guò) @NotNull 校驗(yàn)。
- 誤區(qū) 2:@NotEmpty 能校驗(yàn)基本類型
錯(cuò)誤!基本類型(如 int、boolean)無(wú)法為 null(默認(rèn)有初始值,如 int 為 0),且無(wú) “內(nèi)容” 概念,使用 @NotEmpty 會(huì)觸發(fā)編譯錯(cuò)誤。
- 誤區(qū) 3:項(xiàng)目中直接用 @NotEmpty 替代 @NotNull
不推薦!@NotEmpty 依賴 Hibernate Validator,若未來(lái)切換 Validation 實(shí)現(xiàn)(如從 Hibernate Validator 改為 Apache BVal),@NotEmpty 會(huì)失效;且部分場(chǎng)景(如基本類型包裝類、自定義對(duì)象)無(wú)需校驗(yàn) “內(nèi)容”,用 @NotNull 更輕量。
五、總結(jié)
- 若需標(biāo)準(zhǔn)、通用的 “非 null” 校驗(yàn),且不依賴具體實(shí)現(xiàn),用 @NotNull;
- 若需 **“非 null + 非空內(nèi)容” 的增強(qiáng)校驗(yàn) **(如字符串、集合),且項(xiàng)目已引入 Hibernate Validator,用 @NotEmpty;
- 核心原則:“最小必要校驗(yàn)”—— 只校驗(yàn)業(yè)務(wù)需要的范圍,避免冗余。
到此這篇關(guān)于Java 注解@NotNull 和 @NotEmpty區(qū)別的文章就介紹到這了,更多相關(guān)java @NotNull 和 @NotEmpty區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
鴻蒙中的設(shè)備權(quán)限管理與申請(qǐng)?jiān)敿?xì)示例代碼
在移動(dòng)應(yīng)用開(kāi)發(fā)中,權(quán)限管理是至關(guān)重要的一部分,尤其是在涉及用戶隱私或系統(tǒng)資源(如相機(jī)、位置、存儲(chǔ)等)的應(yīng)用中,這篇文章主要介紹了鴻蒙中的設(shè)備權(quán)限管理與申請(qǐng)的相關(guān)資料,需要的朋友可以參考下2025-08-08
Java中string和int的互相轉(zhuǎn)換問(wèn)題
本文通過(guò)實(shí)例代碼給大家詳細(xì)介紹了Java中string和int的互相轉(zhuǎn)換問(wèn)題,感興趣的朋友一起看看吧2017-10-10
Java中定時(shí)任務(wù)的6種實(shí)現(xiàn)方式
這篇文章主要給大家分享的是Java中定時(shí)任務(wù)的6種實(shí)現(xiàn)方式,幾乎在所有的項(xiàng)目中,定時(shí)任務(wù)的使用都是不可或缺的,如果使用不當(dāng)甚至?xí)斐少Y損,下面文章我們就來(lái)看看Java中定時(shí)任務(wù)的具體使用方式吧2021-10-10
Java并發(fā)工具類之CountDownLatch詳解
這篇文章主要介紹了Java并發(fā)工具類之CountDownLatch詳解,CountDownLatch可以使一個(gè)獲多個(gè)線程等待其他線程各自執(zhí)行完畢后再執(zhí)行,CountDownLatch可以解決那些一個(gè)或者多個(gè)線程在執(zhí)行之前必須依賴于某些必要的前提業(yè)務(wù)先執(zhí)行的場(chǎng)景,需要的朋友可以參考下2023-12-12
基于kafka實(shí)現(xiàn)Spring Cloud Bus消息總線
消息總線是一種通信工具,可以在機(jī)器之間互相傳輸消息、文件等,這篇文章主要介紹了如何利用kafka實(shí)現(xiàn)SpringCloud Bus消息總線,感興趣的可以學(xué)習(xí)一下2022-04-04
Spring Boot集成RabbitMQ的過(guò)程之可靠性與性能提升的問(wèn)題記錄
這篇文章主要介紹了Spring Boot集成RabbitMQ的過(guò)程之可靠性與性能提升的問(wèn)題記錄,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-05-05
MyBatis一級(jí)緩存與二級(jí)緩存原理與作用分析
mybatis-plus是一個(gè)Mybatis的增強(qiáng)工具,在Mybatis的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生,這篇文章帶你了解Mybatis的一級(jí)和二級(jí)緩存2022-12-12

