Java 注解@NotNull 和 @NotEmpty區(qū)別深度解析
要理解這兩個(gè) Java 注解的核心區(qū)別與應(yīng)用場景,需從定義來源、校驗(yàn)邏輯、適用類型三個(gè)維度展開分析,以下是詳細(xì)解讀:
一、核心信息概覽
首先明確兩個(gè)注解的基礎(chǔ)定位,避免混淆:
對比維度 | 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對象)
@NotNull
private String username = "";
@NotNull
private List<String> tags = new ArrayList<>(); // 空集合也會(huì)通過校驗(yàn)
}- @NotEmpty:校驗(yàn) “非 null + 非空內(nèi)容”
是 @NotNull 的增強(qiáng)版,同時(shí)滿足兩個(gè)條件才判定為有效:
public class User {
// 無效:值為null(違反@NotNull)
@NotEmpty
private String username = null;
// 無效:值為""(非null,但空字符串,違反@Size(min=1))
@NotEmpty
private String email = "";
// 無效:值為new ArrayList<>()(非null,但空集合,違反@Size(min=1))
@NotEmpty
private List<String> tags = new ArrayList<>();
}本質(zhì)上,@NotEmpty 的校驗(yàn)邏輯是通過組合注解實(shí)現(xiàn)的(從源碼可見):
// @NotEmpty 源碼中組合了 @NotNull 和 @Size(min=1)
@NotNull // 保證非null
@Size(min = 1) // 保證內(nèi)容長度/大小 ≥1(空內(nèi)容會(huì)觸發(fā)此注解的校驗(yàn)失?。?
public @interface NotEmpty { ... }- 值不能為 null;
- 值的 “內(nèi)容” 不能為空(具體 “空內(nèi)容” 的定義隨類型變化)。
示例(@NotEmpty 判定為無效的情況):
2. 適用數(shù)據(jù)類型:“通用” vs “限定內(nèi)容型”
兩者適用的字段類型不同,@NotEmpty 僅支持 “有內(nèi)容長度 / 大小” 的類型:
數(shù)據(jù)類型 | @NotNull 是否適用 | @NotEmpty 是否適用 | 說明(@NotEmpty 的 “空內(nèi)容” 定義) |
基本類型包裝類 | 是(如 Integer) | 否(無 “內(nèi)容” 概念) | 如 Integer age = null:@NotNull 校驗(yàn),@NotEmpty 不支持 |
String | 是 | 是 | “空內(nèi)容”= 長度為 0 的字符串("") |
集合 / 數(shù)組(如 List、Set、int []) | 是 | 是 | “空內(nèi)容”= 長度 / 大小為 0(如 new ArrayList<>()、new int[0]) |
Map | 是 | 是 | “空內(nèi)容”= 鍵值對數(shù)量為 0(new HashMap<>()) |
自定義對象 | 是(如 User) | 否(無 “內(nèi)容” 概念) | 僅需判斷對象是否為 null,用 @NotNull 即可 |
3. 依賴與兼容性:“標(biāo)準(zhǔn)” vs “擴(kuò)展”
- @NotNull:無額外依賴
屬于 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>
三、使用場景選擇建議
根據(jù)業(yè)務(wù)需求選擇注解,避免 “過度校驗(yàn)” 或 “校驗(yàn)不足”:
業(yè)務(wù)需求 | 推薦注解 | 示例場景 |
僅需確保值 “存在”(非 null),不關(guān)心內(nèi)容 | @NotNull | 1. 年齡(Integer age,允許 0 但不允許 null);2. 自定義對象(User user,只要對象非 null 即可) |
需確保值 “存在且有意義”(非 null + 非空內(nèi)容) | @NotEmpty | 1. 用戶名(String username,不允許 null 或 “”);2. 用戶標(biāo)簽(List<String> tags,不允許 null 或空集合);3. 地址(String address,不允許 null 或空字符串) |
四、常見誤區(qū)提醒
- 誤區(qū) 1:@NotNull 能校驗(yàn)空字符串 / 空集合
錯(cuò)誤!@NotNull 只管 “是否為 null”,空字符串("")、空集合(new ArrayList<>())都是非 null 值,會(huì)通過 @NotNull 校驗(yàn)。
- 誤區(qū) 2:@NotEmpty 能校驗(yàn)基本類型
錯(cuò)誤!基本類型(如 int、boolean)無法為 null(默認(rèn)有初始值,如 int 為 0),且無 “內(nèi)容” 概念,使用 @NotEmpty 會(huì)觸發(fā)編譯錯(cuò)誤。
- 誤區(qū) 3:項(xiàng)目中直接用 @NotEmpty 替代 @NotNull
不推薦!@NotEmpty 依賴 Hibernate Validator,若未來切換 Validation 實(shí)現(xiàn)(如從 Hibernate Validator 改為 Apache BVal),@NotEmpty 會(huì)失效;且部分場景(如基本類型包裝類、自定義對象)無需校驗(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud配置客戶端ConfigClient接入服務(wù)端
這篇文章主要為大家介紹了SpringCloud配置客戶端ConfigClient接入服務(wù)端,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
SpringBoot靜態(tài)資源的訪問方法詳細(xì)介紹
最近在做SpringBoot項(xiàng)目的時(shí)候遇到了“白頁”問題,通過查資料對SpringBoot訪問靜態(tài)資源做了總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09
解讀@ConfigurationProperties使用時(shí)的幾個(gè)常見誤區(qū)
在Spring Boot中,@ConfigurationProperties注解用于綁定配置文件中的屬性到Java對象,它支持properties和yml文件格式,并且可以通過prefix屬性指定配置屬性的前綴,需要注意的是,@PropertySource注解默認(rèn)只支持properties文件,不支持yml文件2024-10-10
深入學(xué)習(xí)java并發(fā)包ConcurrentHashMap源碼
這篇文章主要介紹了深入學(xué)習(xí)java并發(fā)包ConcurrentHashMap源碼,整個(gè) ConcurrentHashMap 由一個(gè)個(gè) Segment 組成,Segment 代表”部分“或”一段“的意思,所以很多地方都會(huì)將其描述為分段鎖。,需要的朋友可以參考下2019-06-06

