Java中泛型學(xué)習(xí)之細(xì)節(jié)篇
簡(jiǎn)介
泛型的作用就是把類(lèi)型參數(shù)化,也就是我們常說(shuō)的類(lèi)型參數(shù)
平時(shí)我們接觸的普通方法的參數(shù),比如public void fun(String s);參數(shù)的類(lèi)型是String,是固定的
現(xiàn)在泛型的作用就是再將String定義為可變的參數(shù),即定義一個(gè)類(lèi)型參數(shù)T,比如public static <T> void fun(T t);
這時(shí)參數(shù)的類(lèi)型就是T的類(lèi)型,是不固定的
從上面的String和T來(lái)看,泛型有著濃濃的多態(tài)的味道,但實(shí)際上泛型跟多態(tài)還是有區(qū)別的
從本質(zhì)上來(lái)講,多態(tài)是Java中的一個(gè)特性,一個(gè)概念,泛型是真實(shí)存在的一種類(lèi)型;
正文中大部分示例都是以集合中的泛型為例來(lái)做介紹,因?yàn)橛玫谋容^多,大家都熟悉
正文
什么是類(lèi)型參數(shù)
類(lèi)型參數(shù)就是參數(shù)的類(lèi)型,它接受類(lèi)作為實(shí)際的值
白話一點(diǎn)來(lái)說(shuō),就是你可以把類(lèi)型參數(shù)看作形參,把實(shí)際傳入的類(lèi)看作實(shí)參
比如:ArrayList<E>中的類(lèi)型參數(shù)E看做形參, ArrayList<String>中的類(lèi)String看做實(shí)參
如果你學(xué)過(guò)工廠設(shè)計(jì)模式,那么就可以把這里的ArrayList<E>看做一個(gè)工廠類(lèi),然后你需要什么類(lèi)型的ArrayList,就傳入對(duì)應(yīng)的類(lèi)型參數(shù)即可
比如,傳入Integer則為ArrayList<Integer>類(lèi)
比如,傳入String則為ArrayList<String>類(lèi)
為啥要有泛型
主要是為了提高代碼可讀性和安全性
具體的要從泛型的演變史說(shuō)起
泛型的演變史
從廣義上來(lái)說(shuō),泛型很早就有了,只是隱式存在的;
比如List list = new ArrayList(); //等價(jià)于List<Object> list = new ArrayList<>();
但是這個(gè)時(shí)候的泛型是很脆弱的,可讀性和安全性都很差(這個(gè)時(shí)期的集合相對(duì)于數(shù)組來(lái)說(shuō),優(yōu)勢(shì)還不是很大)
首先,填充數(shù)據(jù)時(shí),沒(méi)有類(lèi)型檢查,那就有可能把Cat放到Dog集合中
其次,取出時(shí),需要類(lèi)型轉(zhuǎn)換,如果你很幸運(yùn)的把對(duì)象放錯(cuò)了集合(有可能是故意的),那么運(yùn)行時(shí)就會(huì)報(bào)錯(cuò)轉(zhuǎn)換異常(但是編譯卻可以通過(guò))
不過(guò)到了JDK1.5,出現(xiàn)了真正意義上的泛型(類(lèi)型參數(shù),用尖括號(hào)<>表示);
比如List<E>
集合類(lèi),其中的E就是泛型的類(lèi)型參數(shù),因?yàn)榧现卸际谴娴脑谽lement,所以用E字母替代(類(lèi)似還有T,S,K-key,V-value);
這個(gè)時(shí)候,程序的健壯性就提高了,可讀性和安全性也都很高,看一眼就知道放進(jìn)去的是個(gè)啥東西(這個(gè)時(shí)期的集合相對(duì)于數(shù)組來(lái)說(shuō),優(yōu)勢(shì)就很明顯了)
現(xiàn)在拿List<Dog> list = new ArrayList<>()
;來(lái)舉例說(shuō)明
首先,填充數(shù)據(jù)時(shí),編譯器自己會(huì)進(jìn)行類(lèi)型檢查,防止將Cat放入Dog中
其次,取出數(shù)據(jù)時(shí),不需要我們手動(dòng)進(jìn)行類(lèi)型轉(zhuǎn)換,編譯器自己會(huì)進(jìn)行類(lèi)型轉(zhuǎn)換
細(xì)心的你可能發(fā)現(xiàn)了,既然有了泛型,那我放進(jìn)去的是Dog,取出的不應(yīng)該也是Dog嗎?為啥編譯器還要類(lèi)型轉(zhuǎn)換呢?
這里就引出類(lèi)型擦除的概念
類(lèi)型擦除
什么是類(lèi)型擦除?
類(lèi)型擦除指的是,你在給類(lèi)型參數(shù)<T>賦值時(shí),編譯器會(huì)將實(shí)參類(lèi)型擦除為Object(這里假設(shè)沒(méi)有限定符,限定符下面會(huì)講到)
所以這里我們要明白一個(gè)東西:虛擬機(jī)中沒(méi)有泛型類(lèi)型對(duì)象的概念,在它眼里所有對(duì)象都是普通對(duì)象
比如下面的代碼
擦除前
public?class?EraseDemo<T>?{ ? ?private?T?t; ? ?public?static?void?main(String[]?args) { ? ? ? ? ? } ? ?public?T?getT(){ ? ? ? ?return?t; ? } ? ?public?void?setT(T?t){ ? ? ? ?this.t?=?t; ? } }
擦除后
public?class?EraseDemo?{ ? ?private?Object?t; ? ?public?static?void?main(String[]?args) { ? ? ? ? ? } ? ?public?Object?getT(){ ? ? ? ?return?t; ? } ? ?public?void?setT(Object?t){ ? ? ? ?this.t?=?t; ? } }
可以看到,T都變成了Object
泛型類(lèi)被擦除后的類(lèi)型,我們一般叫它原始類(lèi)型(raw type),比如EraseDemo<T>擦除后的原始類(lèi)型就是EraseDemo
相應(yīng)的,如果你有兩個(gè)數(shù)組列表,ArrayList<String>和ArrayList<Integer> ,編譯器也會(huì)把兩者都擦除為ArrayList
你可以通過(guò)代碼來(lái)測(cè)試一下
ArrayList<String>?list1?=?new?ArrayList<>(); ArrayList<Integer>?list2?=?new?ArrayList<>(); System.out.println(list1.getClass()?==?list2.getClass());// 這里會(huì)打印true
上面提到的限定符是干嘛的?
限定符就是用來(lái)限定邊界的,如果泛型有設(shè)置邊界,比如<T extends Animal>
,那么擦除時(shí),會(huì)擦除到第一個(gè)邊界Animal類(lèi),而不是Object類(lèi)
下面還是以上面的代碼為例,展示下擦除前后的對(duì)比
擦除前:
public?class?EraseDemo<T?extends?Animal>?{ ? ?private?T?t; ? ?public?static?void?main(String[]?args) { ? ? ? ? ? } ? ?public?T?getT(){ ? ? ? ?return?t; ? } ? ?public?void?setT(T?t){ ? ? ? ?this.t?=?t; ? } }
擦除后:
public?class?EraseDemo?{ ? ?private?Animal?t; ? ?public?static?void?main(String[]?args) { ? ? ? ? ? } ? ?public?Animal?getT(){ ? ? ? ?return?t; ? } ? ?public?void?setT(Animal?t){ ? ? ? ?this.t?=?t; ? } }
這里的extends符號(hào)是表示繼承的意思嗎?
不是的,這里的extends只是表示前者是后者的一個(gè)子類(lèi),可以繼承也可以實(shí)現(xiàn)
之所以用extends只是因?yàn)檫@個(gè)關(guān)鍵詞已經(jīng)內(nèi)置在Java中了,且比較符合情景
如果自己再造一個(gè)關(guān)鍵詞,比如sub,可能會(huì)使得某些舊代碼產(chǎn)生問(wèn)題(比如使用sub作為變量的代碼)
為什么要擦除呢?
這其實(shí)不是想不想擦除的問(wèn)題,而是不得不擦除的問(wèn)題
因?yàn)榕f代碼是沒(méi)有泛型概念的,這里的擦除主要是為了兼容舊代碼,使得舊代碼和新代碼可以互相調(diào)用
泛型的應(yīng)用場(chǎng)景
從大的方向來(lái)說(shuō):
用在類(lèi)中:叫做泛型類(lèi),類(lèi)名后面緊跟<類(lèi)型參數(shù)>,比如ArrayList<E>
用在方法中:叫做泛型方法,方法的返回值前面添加<類(lèi)型參數(shù)>,比如:public <T> void fun(T obj)
是不是想到了抽象類(lèi)和抽象方法?
還是有區(qū)別的,抽象類(lèi)和抽象方法是相互關(guān)聯(lián)的,但是泛型類(lèi)和泛型方法之間沒(méi)有聯(lián)系
集中到類(lèi)的方向來(lái)說(shuō):泛型多用在集合類(lèi)中,比如ArrayList<E>
如果是自定義泛型的話,推薦用泛型方法,原因有二:
脫離泛型類(lèi)單獨(dú)使用,使代碼更加清晰(不用為了某個(gè)小功能而泛化整個(gè)類(lèi))
泛型類(lèi)中,靜態(tài)方法無(wú)法使用類(lèi)型參數(shù);但是靜態(tài)的泛型方法可以
通配符限定
這里主要介紹<T>, <? extends T>, <? super T>的區(qū)別
<T>:這個(gè)是最常用的,就是普通的類(lèi)型參數(shù),在調(diào)用時(shí)傳入實(shí)際的類(lèi)來(lái)替換T即可,這個(gè)實(shí)際的類(lèi)可以是T,也可以是T的子類(lèi)
比如List<String> list = new ArrayList<>();,這里的String就是實(shí)際傳入的類(lèi),用來(lái)替換類(lèi)型參數(shù)T
<? extends T>:這個(gè)屬于通配符限定中的子類(lèi)型限定,即傳入實(shí)際的類(lèi)必須是T或者T子類(lèi)
乍一看,這個(gè)有點(diǎn)像<T>類(lèi)型參數(shù),都是往里放T或者T的子類(lèi);
但是區(qū)別還是挺多的,后面會(huì)列出
<? super T>:這個(gè)屬于通配符限定中的超類(lèi)型限定,即傳入實(shí)際的類(lèi)必須是T或者T的父類(lèi)
<?>:這個(gè)屬于無(wú)限定通配符,即它也不知道里面該放啥類(lèi)型,所以干脆就不讓你往里添加,只能獲?。ㄟ@一點(diǎn)類(lèi)似<? extends T>)
下面用表格列出<T>,<? extends T>, <? super T>的幾個(gè)比較明細(xì)的區(qū)別
<T> | <? extends T> | <? super T> | |
---|---|---|---|
類(lèi)型擦除 | 傳入實(shí)參時(shí),實(shí)參被擦為Object,但是在get時(shí)編譯器會(huì)自動(dòng)轉(zhuǎn)為T(mén) | 擦到T | 擦到Object |
引用對(duì)象 | 不能將引用指向子類(lèi)型或者父類(lèi)型的對(duì)象,比如:List<Animal> list = new ArrayList<Cat>();//報(bào)錯(cuò) | 能將引用指向子類(lèi)型的對(duì)象,比如:List<? extends Animal> list = new ArrayList<Cat>(); | 能將引用指向父類(lèi)型的對(duì)象,比如:List<? super Cat> list = new ArrayList<Animal>(); |
添加數(shù)據(jù) | 可以添加數(shù)據(jù),T或者T的子類(lèi) | 不能 | 能,T或者T的子類(lèi) |
下面我們用代碼來(lái)演示下
類(lèi)型擦除:
// <T>類(lèi)型,傳入實(shí)參時(shí),擦除為Object,但是get時(shí)還是實(shí)參的類(lèi)型 List<Animal>?list1?=?new?ArrayList<>();// 合法 list1.add(new?Dog());// 合法 Animal?animal?=?list1.get(0);?// 這里不需要強(qiáng)轉(zhuǎn),雖然前面?zhèn)魅雽?shí)參時(shí)被擦除為Object,但是get時(shí)編譯器內(nèi)部已經(jīng)做了強(qiáng)制類(lèi)型轉(zhuǎn)換 // <? extends T> 子類(lèi)型的通配符限定,擦除到T(整個(gè)過(guò)程不再變) List<??extends?Animal>?list2?=?list1;// 合法 Animal?animal2?=?list2.get(0);?// 這里不需要強(qiáng)轉(zhuǎn),因?yàn)橹徊脸絋(即Animal) // <? super T> 超類(lèi)型的通配符限定,擦除到Object List<??super?Animal>?list3?=?list1;?// 合法 Animal?animal3?=?(Animal)list3.get(0);?// 需要手動(dòng)強(qiáng)制,因?yàn)楸徊脸絆bject
將引用指向子類(lèi)型或父類(lèi)型的對(duì)象:
// <T>類(lèi)型,不能指向子類(lèi)型或父類(lèi)型 List<Animal>?list?=?new?ArrayList<Dog>();// 報(bào)錯(cuò):需要的是List<Animal>,提供的是ArrayList<Dog> // <? extends T> 子類(lèi)型的通配符限定,指向子類(lèi)型 List<??extends?Animal>?list2?=?new?ArrayList<Dog>();// 合法 // <? super T> 超類(lèi)型的通配符限定,指向父類(lèi)型 List<??super?Dog>?list3?=?new?ArrayList<Animal>();?// 合法
添加數(shù)據(jù)
// <T>類(lèi)型,可以添加T或者T的子類(lèi)型 List<Animal>?list1?=?new?ArrayList<>(); list.add(new?Dog());// 合法 // <? extends T> 子類(lèi)型的通配符限定,不能添加元素 List<??extends?Animal>?list2?=?new?ArrayList<Dog>();// 正確 list2.add(new?Dog());?// 報(bào)錯(cuò):不能往里添加元素 // <? super T> 超類(lèi)型的通配符限定,可以添加T或者T的子類(lèi)型 List<??super?Dog>?list3?=?new?ArrayList<Animal>(); list3.add(new?Dog());?// 合法,可以添加T類(lèi)型的元素 list3.add(new?Animal());//報(bào)錯(cuò),不能添加父類(lèi)型的元素
下面針對(duì)上面的測(cè)試結(jié)果進(jìn)行解惑
先從<T>的報(bào)錯(cuò)開(kāi)始吧
為啥<T>類(lèi)型的引用不能指向子類(lèi)型,比如 List<Animal> list = new ArrayList<Dog>();
首先說(shuō)明一點(diǎn),Animal和Dog雖然是父子關(guān)系(Dog繼承Animal),但是List<Animal> 和 List<Dog>之間是沒(méi)有任何關(guān)系的(有點(diǎn)像Java和Javascript)
他們之間的關(guān)系如下圖
之所以這樣設(shè)計(jì),主要是為了類(lèi)型安全的考慮
下面用代碼演示,假設(shè)可以將List<Animal>指向子類(lèi)List<Dog>
List<Animal>?list?=?new?ArrayList<Dog>();// 假設(shè)這里不報(bào)錯(cuò) list.add(new?Cat());?//這里把貓放到狗里面了
第二行可以看到,很明顯,把貓放到狗里面是不對(duì)的,這就又回到了泛型真正出現(xiàn)之前的時(shí)期了(沒(méi)有泛型,集合存取數(shù)據(jù)時(shí)不安全)
那為啥<? extends T>就能指向子類(lèi)型呢?比如List<? extends Animal> list = new ArrayList<Dog>();
說(shuō)的淺一點(diǎn),原因是:這個(gè)通配符限定出現(xiàn)的目的就是為了解決上面的不能指向子類(lèi)的問(wèn)題
當(dāng)然,這個(gè)原因說(shuō)了跟沒(méi)說(shuō)一樣。下面開(kāi)始正經(jīng)點(diǎn)解釋吧
因?yàn)檫@個(gè)通配符限定不允許插入任何數(shù)據(jù),所以當(dāng)你指向子類(lèi)型時(shí),這個(gè)list就只能存放指向的那個(gè)集合里的數(shù)據(jù)了,而不能再往里添加;
自然的也就類(lèi)型安全了,只能訪問(wèn),不能添加
為什么<? extends T>不允許插入數(shù)據(jù)呢?
其實(shí)這個(gè)的原因跟上面的修改引用對(duì)象是相輔相成的,合起來(lái)就是為了保證泛型的類(lèi)型安全性
考慮下面的代碼
List<Animal>?list?=?new?ArrayList<>(); list.add(new?Cat()); list.add(new?Dog()); Dog?d?=?(Dog)?list.get(0);?// 報(bào)錯(cuò),轉(zhuǎn)換異常
可以看到,插入的子類(lèi)很混亂,導(dǎo)致提取時(shí)轉(zhuǎn)型容易出錯(cuò)(這是泛型<T>的一個(gè)弊端,當(dāng)然我們寫(xiě)的時(shí)候多用點(diǎn)心可能就不會(huì)這個(gè)問(wèn)題)
但是有了<? extends T>之后,就不一樣了
首先你可以通過(guò)修改引用的對(duì)象來(lái)使得list指向不同的Animal子類(lèi)
其次你添加數(shù)據(jù),不能直接添加,但是可以通過(guò)指向的Animal子類(lèi)對(duì)象來(lái)添加
這樣就保證了類(lèi)型的安全性
代碼如下:
// 定義一個(gè)Dog集合 List<Dog>?listDog?=?new?ArrayList<>(); listDog.add(new?Dog()); // 讓<? extends Animal>通配符限定的泛型 指向上面的Dog集合 List<??extends?Animal>?list2?=?listDog; // 這時(shí)如果想往里添加數(shù)據(jù),只需要操作listDog即可,它可以保證類(lèi)型安全 listDog.add(new?Dog()); // 如果自己去添加,就會(huì)報(bào)錯(cuò) list2.add(new?Dog());// 報(bào)錯(cuò)
<? extends T>一般用在形參,這樣我們需要哪個(gè)子類(lèi)型,只需要傳入對(duì)應(yīng)子類(lèi)的泛型對(duì)象就可以了,從而實(shí)現(xiàn)泛型中的多態(tài)
<? super T>為啥可以插入呢?
兩個(gè)原因
它只能插入T或者T的子類(lèi)
它的下限是T
也就是說(shuō)你隨便插入,我已經(jīng)限制了你插入的類(lèi)型為T(mén)或者T的子類(lèi)
那么我在查詢(xún)時(shí),就可以放心的轉(zhuǎn)為T(mén)或者T的父類(lèi)
代碼如下:
List<??super?Dog>?listDog?=?new?ArrayList<>(); listDog.add(new?Dog()); listDog.add(new?Cat());?// 報(bào)錯(cuò) listDog.add(new?Animal());?// 報(bào)錯(cuò) Dog?dog?=?(Dog)?listDog.get(0);?// 內(nèi)部被擦除為Object,所以要手動(dòng)強(qiáng)轉(zhuǎn)
為啥<T>獲取時(shí),編譯器會(huì)自動(dòng)強(qiáng)轉(zhuǎn)轉(zhuǎn)換,到了這里<? super T>,就要手動(dòng)轉(zhuǎn)換了呢?
這個(gè)可能是因?yàn)榫幾g器也不確定你的要返回的T的父類(lèi)是什么類(lèi)型,所以干脆留給你自己來(lái)處理了
但是如果你把這個(gè)listDog指向一個(gè)父類(lèi)的泛型對(duì)象,然后又在父類(lèi)的泛型對(duì)象中,插入其他類(lèi)型,那可就亂了(又回到<T>的問(wèn)題了,要自己多注意)
比如:
List<Animal>?list?=?new?ArrayList<>(); list.add(new?Cat());?// 加了Cat // 指向Animal List<??super?Dog>?listDog?=?list; listDog.add(new?Dog()); list.add(new?Cat());?// 報(bào)錯(cuò) list.add(new?Animal());?// 報(bào)錯(cuò) Dog?dog?=?(Dog)?listDog.get(0);?//報(bào)錯(cuò):轉(zhuǎn)換異常Cat-》Dog
所以建議<? super T>在添加數(shù)據(jù)的時(shí)候,盡量集中在一個(gè)地方,不要多個(gè)地方添加,像上面的,要么都在<? super Dog>里添加數(shù)據(jù),要么都在<Animal>中添加
動(dòng)態(tài)類(lèi)型安全檢查
這個(gè)主要是為了跟舊代碼兼容,對(duì)舊代碼進(jìn)行的一種類(lèi)型安全檢查,防止將Cat插入Dog集合中這種錯(cuò)誤
這種檢查是發(fā)生在編譯階段,這樣就可以提早發(fā)現(xiàn)問(wèn)題
對(duì)應(yīng)的類(lèi)為Collections工具類(lèi),方法如下圖
代碼如下
// 動(dòng)態(tài)類(lèi)型安全檢查,在與舊代碼兼容時(shí),防止將Dog放到Cat集合中類(lèi)似的問(wèn)題 // === 檢查之前 === List?list?=?new?ArrayList<Integer>(); // 添加不報(bào)錯(cuò) list.add("a"); list.add(1); // 只有用的時(shí)候,才會(huì)報(bào)錯(cuò) Integer?i?=?(Integer)?list.get(0);?// 這里運(yùn)行時(shí)報(bào)錯(cuò) // === 檢查之后 === List?list2?=?Collections.checkedList(new?ArrayList<>(),?Integer.class); // 插入時(shí)就會(huì)報(bào)錯(cuò) list2.add("a");?// 這里編譯時(shí)就報(bào)錯(cuò),提前發(fā)現(xiàn)錯(cuò)誤 list2.add(1);
總結(jié)
泛型的作用:
提高類(lèi)型安全性:預(yù)防各種類(lèi)型轉(zhuǎn)換問(wèn)題
增加程序可讀性:所見(jiàn)即所得,看得到放進(jìn)去的是啥,也知道會(huì)取出啥
提高代碼重用性:多種同類(lèi)型的數(shù)據(jù)(比如Animal下的Dog,Cat)可以集合到一處來(lái)處理,從而調(diào)高代碼重用性
類(lèi)型擦除:
泛型T在傳入實(shí)參時(shí),實(shí)參的類(lèi)型會(huì)被擦除為限定類(lèi)型(即<? extends T>中的T),如果沒(méi)有限定類(lèi)型,則默認(rèn)為Object
通配符限定:
<? extends T>:子類(lèi)型的通配符限定,以查詢(xún)?yōu)橹?/strong>,比如消費(fèi)者集合場(chǎng)景
<? super T>:超類(lèi)型的通配符限定,以添加為主,比如生產(chǎn)者集合場(chǎng)景
到此這篇關(guān)于Java中泛型學(xué)習(xí)之細(xì)節(jié)篇的文章就介紹到這了,更多相關(guān)Java中泛型細(xì)節(jié)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis的xml中使用if/else標(biāo)簽的具體使用
本文主要介紹了Mybatis的xml中使用if/else標(biāo)簽的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05Java實(shí)現(xiàn)經(jīng)典大富翁游戲的示例詳解
大富翁,又名地產(chǎn)大亨。是一種多人策略圖版游戲。參與者分得游戲金錢(qián),憑運(yùn)氣(擲骰子)及交易策略,買(mǎi)地、建樓以賺取租金。本文將通過(guò)Java實(shí)現(xiàn)這一經(jīng)典游戲,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-02-02MyBatis-Plus實(shí)現(xiàn)邏輯刪除功能解析
這篇文章主要介紹了MyBatis-Plus實(shí)現(xiàn)邏輯刪除功能解析,有時(shí)候并不需要真正的刪除數(shù)據(jù),而是想邏輯刪除,方便數(shù)據(jù)恢復(fù),MyBatis-Plus可以很方便的實(shí)現(xiàn)邏輯刪除的功能,需要的朋友可以參考下2023-11-11BeanUtils.copyProperties()拷貝id屬性失敗的原因及解決
這篇文章主要介紹了BeanUtils.copyProperties()拷貝id屬性失敗的原因及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09SpringBoot圖文并茂講解Lombok庫(kù)的安裝與使用
Lombok想要解決了的是在我們實(shí)體Bean中大量的Getter/Setter方法,以及toString, hashCode等可能不會(huì)用到,但是某些時(shí)候仍然需要復(fù)寫(xiě),以期方便使用的方法;在使用Lombok之后,將由其來(lái)自動(dòng)幫你實(shí)現(xiàn)代碼生成2022-06-06Java使用@Validated注解進(jìn)行參數(shù)驗(yàn)證的方法
這篇文章主要介紹了Java使用@Validated注解進(jìn)行參數(shù)驗(yàn)證的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08