Java泛型

Java 1.5版本中增加了泛型喉誊。

為什么需要引入泛型?
在引入泛型之前,讀取集合中的每一個元素都需要進行轉(zhuǎn)換,如果在集合中插入了錯誤類型的對象妒蔚,那么就會在程序運行時報類型轉(zhuǎn)換的錯誤。在引入泛型后我們可以告訴編譯器需要向集合中插入的元素類型月弛,編譯器會在插入元素時進行自動轉(zhuǎn)換肴盏,并在編譯時報告往集合中插入錯誤類型的代碼。

在Java代碼中還可以繼續(xù)使用原生態(tài)類型例如List等的原因是因為向后兼容帽衙,讓以前未使用泛型的代碼保存合法菜皂,并且能夠與使用泛型的代碼進行交互。在新代碼中不推薦使用List等原生態(tài)類型厉萝。
List 和 List<Object> 區(qū)別恍飘?
兩種集合都允許插入任何類型的對象。簡單說List逃避了編譯器的類型檢查谴垫,而List<Object>則明確告知編譯器其可以保存任何類型的對象章母。

泛型有子類型化的規(guī)則,List<String> 是原生態(tài)類型List的子類型而不是List<Object>的子類型翩剪,所有可以將List<String> 類型的對象傳遞給List類型的參數(shù)但不能傳遞給List<Object>類型的參數(shù):
package template;

import java.util.ArrayList;
import java.util.List;

/**
* @author: zhouzhaoping
* @description:
* @date: 2019-08-25
*/
public class Test1 {

  public static void main(String[] args) {
      List<String> list = new ArrayList<String>();
      list.add("1");
      list.add("2");
      list.add("3");
      list.add("4");
      list.add("5");
      test1(list);
      test2(list); // 報錯
  }

  public static void test1(List list) {
      for (Object o : list) {
          System.out.println("test1:" + o.toString());
      }
  }

  public static void test2(List<Object> list) {
      for (Object o : list) {
          System.out.println("test2:" + o.toString());
      }
  }

}

使用原生態(tài)類型List會失去類型安全性乳怎,使用List<Object>這樣的參數(shù)化類型則不會,為了更好的說明請參考下面的代碼前弯。

public static void main(String[] args) {
      List<String> strings = new ArrayList<String>();
      unsafeAdd(strings, new Integer(42));
      String s = strings.get(0);

  }

  private static void unsafeAdd(List list, Object o) {
      list.add(o);
  }

在最新的Java8中舞肆,上述的代碼已經(jīng)無法通過編譯。
將List替換為List<Object>能看到更明確的報錯信息博杖。

在不確定集合元素類型的情況下使用無限制的通配符類型代替使用原生態(tài)類型

如果你需要篩選集合的交集椿胯,使用原生態(tài)類型你可以這樣寫:

public static int numElementsInCommon(Set s1, Set s2) {
      int result = 0;
      for (Object o1: s1) {
          if (s2.contains(o1)) {
              result++;
          }
      }
      return result;
  }

由于使用了原生類型,這樣寫是很危險的剃根。
如果要定義一個參數(shù)化的類型(例如List<String>,因為不能使用List<E>定義)哩盲,但不確定或不關(guān)心實際的參數(shù)類型則可以使用一個?來代替狈醉。

public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
        int result = 0;
        for (Object o1: s1) {
            if (s2.contains(o1)) {
                result++;
            }
        }
        return result;
    }

可以將任何元素放入原生態(tài)類型的集合中廉油,因此很容易破壞該集合的類型約束條件,例如如下代碼可通過編譯:

public static int numElementsInCommon(Set s1, Set s2) {
        int result = 0;
        for (Object o1: s1) {
            if (s2.contains(o1)) {
                result++;
            }
        }
        s1.add("1");
        s2.add(2);
        return result;
    }

但如下代碼卻不行:

public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
        int result = 0;
        for (Object o1: s1) {
            if (s2.contains(o1)) {
                result++;
            }
        }
        s1.add("1");
        s2.add(2);
        return result;
    }

通過以上例子不難看出苗傅?通配符主要使用在函數(shù)的形參上且在該函數(shù)內(nèi)部不會修改該集合的場景中抒线。

數(shù)組與泛型

數(shù)組與泛型相比有兩個重要的不同點,第一個是數(shù)組是協(xié)變的而泛型不是渣慕,例如如果Sub是Super的子類型嘶炭,那么Sub[]也是Super[]的子類型抱慌。相反泛型則是不可變的:對于任意兩個不同的類型Type1和Type2,List<Type1>和List<Type2>沒有關(guān)系( 其實這是數(shù)組設(shè)計的缺陷而不是泛型)眨猎。
這個不同導(dǎo)致使用泛型可以比使用數(shù)組更容易發(fā)現(xiàn)錯誤抑进,參考如下的代碼:

public static void main(String[] args) {
        Object[] objectArray = new Long[1];
        objectArray[0] = "I don't fit in.";

    }

這段代碼可以通過編譯但在執(zhí)行時會拋出異常。

public static void main(String[] args) {
        List<Object> o1 = new ArrayList<Long>();
        o1.add("I don't fit in.");
    }

而這段代碼則無法通過編譯睡陪,對比數(shù)組我們可以更早的發(fā)現(xiàn)錯誤寺渗。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市兰迫,隨后出現(xiàn)的幾起案子信殊,更是在濱河造成了極大的恐慌,老刑警劉巖汁果,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸡号,死亡現(xiàn)場離奇詭異,居然都是意外死亡须鼎,警方通過查閱死者的電腦和手機鲸伴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晋控,“玉大人汞窗,你說我怎么就攤上這事∩囊耄” “怎么了仲吏?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝌焚。 經(jīng)常有香客問我裹唆,道長,這世上最難降的妖魔是什么只洒? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任许帐,我火速辦了婚禮,結(jié)果婚禮上毕谴,老公的妹妹穿的比我還像新娘成畦。我一直安慰自己,他們只是感情好涝开,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布循帐。 她就那樣靜靜地躺著,像睡著了一般舀武。 火紅的嫁衣襯著肌膚如雪拄养。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天银舱,我揣著相機與錄音瘪匿,去河邊找鬼跛梗。 笑死,一個胖子當著我的面吹牛柿顶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播操软,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼嘁锯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聂薪?” 一聲冷哼從身側(cè)響起家乘,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藏澳,沒想到半個月后仁锯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡翔悠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年业崖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蓄愁。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡双炕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撮抓,到底是詐尸還是另有隱情妇斤,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布丹拯,位于F島的核電站站超,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏乖酬。R本人自食惡果不足惜死相,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咬像。 院中可真熱鬧媳纬,春花似錦、人聲如沸施掏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽七芭。三九已至素挽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狸驳,已是汗流浹背预明。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工缩赛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撰糠。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓酥馍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親阅酪。 傳聞我的和親對象是個殘疾皇子旨袒,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java1.5版本中增加了泛型。在沒有泛型之前术辐,從集合中讀取到的每一個對象都必須進行轉(zhuǎn)換砚尽。如果不小心插入了錯誤類型...
    塞外的風(fēng)閱讀 822評論 0 0
  • 前言 Java 5 添加了泛型,提供了編譯時類型安全檢測機制辉词,該機制允許程序員在編譯時檢測到非法的類型必孤。泛型的本質(zhì)...
    czwbig閱讀 497評論 0 0
  • 閱讀目錄 一、為什么會出現(xiàn)泛型 二瑞躺、泛型會帶來什么樣的問題 1. 不能用基本類型實例化類型參數(shù) 2. 不能用于運行...
    架構(gòu)師Javaspring閱讀 3,489評論 0 0
  • 參數(shù)類型的好處 在 Java 引入泛型之前敷搪,泛型程序設(shè)計是用繼承實現(xiàn)的。ArrayList 類只維護一個 Obje...
    杰哥長得帥閱讀 882評論 0 3
  • 當你決定做一件事的時候幢哨,你必須在72小時之內(nèi)完成它购啄,否則你很可能永遠不會做了≈雒矗總而言之狮含,就是要立即去做,不要有太多...
    旖旎風(fēng)光護你行閱讀 179評論 0 0