<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java泛型詳解,通俗易懂只需5分鐘

          共 4727字,需瀏覽 10分鐘

           ·

          2022-01-13 16:49

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          Java術(shù)?|?

          從Java1.5開(kāi)始,官方引入了泛型機(jī)制,事實(shí)上,從1.3版本開(kāi)始,泛型就已經(jīng)存在了,經(jīng)過(guò)歷代的發(fā)展,已足具雛形,本篇文章就來(lái)學(xué)習(xí)一下泛型的使用。


          01

          認(rèn)識(shí)泛型


          在此之前,我們先來(lái)認(rèn)識(shí)一下泛型吧,先看一段示例:

          public class Main {

          public static void main(String[] args) {
          List list = new ArrayList();
          list.add(1);
          list.add(2);
          list.add(3);
          dealList(list);
          }

          public static void dealList(List list) {
          int result = 0;
          for (Object obj : list) {
          int num = (int) obj;
          result += num;
          }
          System.out.println(result);
          }
          }

          在該示例中,dealList方法用于計(jì)算一個(gè)集合中的元素和,當(dāng)然,只有數(shù)字才能夠參與運(yùn)算,但是示例中的list是可以存放任意對(duì)象的,所以很可能會(huì)出現(xiàn)如下情況:

          public static void main(String[] args) {
          List list = new ArrayList();
          list.add(1);
          list.add(2);
          list.add(3);
          list.add("4");
          dealList(list);
          }

          因?yàn)樽址疅o(wú)法轉(zhuǎn)為整型,所以程序會(huì)報(bào)錯(cuò):

          Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

          這時(shí)候泛型的約束就顯得尤為重要,在定義集合的時(shí)候?qū)ζ溥M(jìn)行類型的限定即可在編譯期就避免這一類問(wèn)題:


          02

          定義泛型類


          泛型的用法十分多樣,它可以作用在類、方法上實(shí)現(xiàn)各種功能,先來(lái)了解一下泛型類的定義。

          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class Genericity {

          private String str1;
          private String str2;
          }

          以上是一個(gè)簡(jiǎn)單的Java類,我們想通過(guò)它計(jì)算其中兩個(gè)屬性值的和:

          public static void main(String[] args) {
          Genericity genericity = new Genericity("1","1");
          String str1 = genericity.getStr1();
          String str2 = genericity.getStr2();
          Integer num1 = Integer.valueOf(str1);
          Integer num2 = Integer.valueOf(str2);
          int result = num1 + num2;
          System.out.println(result);
          }

          但此時(shí)我覺(jué)得將屬性定義為String是一個(gè)錯(cuò)誤的決定,因?yàn)橛?jì)算屬性值的和還需要自己對(duì)類型進(jìn)行轉(zhuǎn)換,所以我將屬性調(diào)整為了Integer類型:

          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class Genericity {

          private Integer str1;
          private Integer str2;
          }

          當(dāng)然了,這個(gè)例子可能有一些牽強(qiáng),事實(shí)上不會(huì)有人這么做,但目的很明顯,就是想讓類中的屬性類型可變,使得整個(gè)類更加靈活,基于此需求,我們可以使用泛型對(duì)其進(jìn)行改造:

          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class Genericity {

          private T t1;
          private T t2;
          }

          這就是泛型類的定義,通過(guò)在類名后面添加符號(hào)即可定義泛型類,而類中的屬性類型均為T,這將導(dǎo)致類中的屬性類型會(huì)跟隨T的變化而變化,用法如下:

          public static void main(String[] args) {
          Genericity<Integer> genericity = new Genericity<>(1, 1);
          Integer t1 = genericity.getT1();
          Integer t2 = genericity.getT2();
          int result = t1 + t2;
          System.out.println(result);
          }

          在創(chuàng)建泛型類對(duì)象時(shí),同樣在類名后添加,此時(shí)Integer就作為了T符合的內(nèi)容,所以類中的屬性都將是Integer類型。如果類名后添加,則類中的屬性均為String類型。

          實(shí)際上,泛型類可以定義多個(gè)泛型變量,比如:

          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class GenericityU> {

          private T t1;
          private U t2;
          }

          此時(shí)我們?cè)趧?chuàng)建對(duì)象時(shí)就可以傳入兩個(gè)類型:

          public static void main(String[] args) {
          GenericityString> genericity = new Genericity<>(1, "1");
          Integer t1 = genericity.getT1();
          String t2 = genericity.getT2();
          }


          03

          定義泛型方法


          泛型除了作用在類上,還可以作用在方法上,效果與泛型類是相似的。

          public static  void method(T t) {
          }

          只需在調(diào)用方法時(shí)傳入類型即可:

          public static void main(String[] args) {
          Genericity.<Integer>method(1);
          }

          而事實(shí)上,你無(wú)需這么寫,因?yàn)榫幾g器能夠自動(dòng)推斷出泛型類型T,所以調(diào)用泛型方法可以簡(jiǎn)寫為:

          public static void main(String[] args) {
          Genericity.method(1);
          }

          泛型方法的返回值也可以使用類型變量:

          public static  T method(T t) {
          return t;
          }

          當(dāng)然了,泛型方法也支持定義多個(gè)類型變量:

          public static  T method(T t,U u) {
          return t;
          }


          04

          泛型的限定符


          來(lái)看下面的程序:

          public static  T min(T[] t) {
          T minimum = t[0];
          for (int i = 0; i < t.length; i++) {
          if (minimum.compareTo(t[i]) > 0) {
          minimum = t[i];
          }
          }
          return minimum;
          }

          能看得出來(lái)這段程序在干什么嗎?是的,它能夠取出數(shù)組t中的最小值,然而這段程序是有問(wèn)題的,因?yàn)門可以是任意類型的對(duì)象,但不是什么對(duì)象都能夠調(diào)用compareTo方法進(jìn)行比較的,所以,我們需要對(duì)類型變量T進(jìn)行限定,限定為實(shí)現(xiàn)了Comparable接口的對(duì)象,如下:

          public static  T min(T[] t) {
          T minimum = t[0];
          for (int i = 0; i < t.length; i++) {
          if (minimum.compareTo(t[i]) > 0) {
          minimum = t[i];
          }
          }
          return minimum;
          }

          一個(gè)泛型方法也可以對(duì)類型變量進(jìn)行多個(gè)限定:

          public static  T min(T[] t) {
          ......
          }


          05

          泛型擦除


          需要知道的是,泛型僅僅是在編譯期間起作用,目的是讓程序員在編譯期間就避免發(fā)生一些類型不對(duì)應(yīng)的問(wèn)題,而在運(yùn)行階段,泛型是根本不存在的,因?yàn)樘摂M機(jī)會(huì)對(duì)泛型進(jìn)行擦除。

          我們可以通過(guò)反射進(jìn)行驗(yàn)證,因?yàn)榉瓷涫亲饔迷谶\(yùn)行階段的:

          public static void main(String[] args) throws Exception {
          List list = new ArrayList<>();
          list.add(1);
          Method addMethod = list.getClass().getDeclaredMethod("add",Object.class);
          addMethod.invoke(list,"2");
          addMethod.invoke(list,true);
          addMethod.invoke(list,3.2f);
          System.out.println(list);
          }

          若是通過(guò)反射能夠?qū)⑦@些非Integer類型的值存入list,則說(shuō)明在運(yùn)行期間確實(shí)是不存在泛型檢查的,運(yùn)行結(jié)果如下:

          [1, 2, true, 3.2]

          泛型擦除也體現(xiàn)在泛型方法中,回顧之前的例子:

          public static  T min(T[] t) {
          ......
          }

          當(dāng)程序運(yùn)行期間,泛型會(huì)被擦除,此時(shí)方法變?yōu)槿缦拢?/p>

          public static Comparable min(Comparable t) {
          ......
          }

          這也就是為什么類型限定能夠生效的原因了,通過(guò)泛型擦除后,該方法就只能接收和返回Comparable接口的實(shí)現(xiàn)類。



          06

          泛型通配符


          固定的泛型類型顯然無(wú)法滿足復(fù)雜多變的需求,為此,泛型設(shè)計(jì)者們還提供了泛型通配符,如:

          Genericity extends Person>

          它表示類型變量必須是Person類型的子類。當(dāng)然了,泛型通配符還有超類型定義的情況:

          Genericitysuper Person>

          此時(shí)類型變量就必須是Person類的超類。

          還有一種情況是無(wú)限定通配符:

          Genericity>

          它和Genericity非常相似,但又有不同,Genericity的setter方法不能被調(diào)用,getter方法只能返回Object類型,不過(guò)這種方式的用法較少,可能會(huì)被用來(lái)判斷空引用:

          public static boolean isNull(Genericity genericity){
          return genericity.getContent();
          }

          本文作者:汪偉俊?為Java技術(shù)迷專欄作者?投稿,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載


          1、致歉!抖音Semi Design承認(rèn)參考阿里Ant Design

          2、對(duì)比7種分布式事務(wù)方案,還是偏愛(ài)阿里開(kāi)源的Seata,真香!

          3、Redis存儲(chǔ)結(jié)構(gòu)體信息,選hash還是string?

          4、掃盲 docker 常用命令

          5、最全分布式Session解決方案

          6、21 款 yyds 的 IDEA插件

          7、真香!用 IDEA 神器看源碼,效率真高!

          點(diǎn)分享

          點(diǎn)收藏

          點(diǎn)點(diǎn)贊

          點(diǎn)在看

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  思思热高清无码播放 | 五月丁香月| 亚洲黄色电影在线免费观看 | 国产黄色在线免费观看 | 久久久久久久电影 |