Java 泛型

Java 泛型

泛型 ( generics ) 提供了編譯時類型安全檢測機制误褪,該機制允許程序員在編譯時檢測到非法的類型

泛型的本質(zhì)是參數(shù)化類型兽间,也就是說所操作的數(shù)據(jù)類型被指定為一個參數(shù)嘀略。

假定我們有這樣一個需求:寫一個排序方法乓诽,能夠?qū)φ蛿?shù)組、字符串數(shù)組甚至其他任何類型的數(shù)組進行排序讼育,該如何實現(xiàn)奶段?

答案是可以使用 Java 泛型

有了 Java 泛型剥纷,我們可以寫一個泛型方法來對一個對象數(shù)組排序,然后,調(diào)用該泛型方法來對整型數(shù)組刺洒、浮點數(shù)數(shù)組逆航、字符串數(shù)組等進行排序

泛型方法

泛型方法是在調(diào)用時可以接收不同類型的參數(shù),根據(jù)傳遞給泛型方法的參數(shù)類型拇惋,編譯器適當?shù)靥幚砻恳粋€方法調(diào)用

定義一個泛型方法需要遵守一定的規(guī)則

  1. 所有泛型方法聲明都有一個類型參數(shù)聲明部分 (由尖括號分隔)撑帖,該類型參數(shù)聲明部分在方法返回類型之前 ( <E> )

  2. 每一個類型參數(shù)聲明部分包含一個或多個類型參數(shù)澳眷,參數(shù)間用逗號隔開

    一個泛型參數(shù),也被稱為一個類型變量衷敌,是用于指定一個泛型類型名稱的標識符

  3. 類型參數(shù)能被用來聲明返回值類型,并且能作為泛型方法得到的實際參數(shù)類型的占位符

  4. 泛型方法體的聲明和其它方法一樣

    注意類型參數(shù)只能代表引用型類型助琐,不能是原始類型 ( 像 int,double,char 等)

范例

下面的代碼定義了一個泛型方法用于打印不同字符串的元素

public class GenericMethodTest
{
   // 泛型方法 printArray 
   public static < E > void printArray( E[] inputArray )
   {
      // 輸出數(shù)組元素 
         for ( E element : inputArray ){        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }

    public static void main( String args[] )
    {
        // 創(chuàng)建不同類型數(shù)組: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };

        System.out.println( "整型數(shù)組元素為:" );
        printArray( intArray  ); // 傳遞一個整型數(shù)組

        System.out.println( "\n雙精度型數(shù)組元素為:" );
        printArray( doubleArray ); // 傳遞一個雙精度型數(shù)組

        System.out.println( "\n字符型數(shù)組元素為:" );
        printArray( charArray ); // 傳遞一個字符型數(shù)組
    } 
}

編譯運行以上 Java 代碼兵钮,輸出結(jié)果如下

整型數(shù)組元素為:
1 2 3 4 5
雙精度型數(shù)組元素為:
1.1 2.2 3.3 4.4
字符型數(shù)組元素為:
H E L L O

有界的類型參數(shù)

泛型很好用侧但,但有時候我們想限制那些被允許傳遞到一個類型參數(shù)的類型種類范圍

例如,一個操作數(shù)字的方法可能只希望接受 Number 或者 Number 子類的實例

這時候就要用到有界類型參數(shù)

要聲明一個有界的類型參數(shù)屁药,首先列出類型參數(shù)的名稱柏锄,后跟 extends 關(guān)鍵字,最后緊跟它的上界

范例

下面的范例演示了 "extends" 如何使用在一般意義上的意思 "extends" (類) 或者 "implements" (接口)

該范例中的泛型方法返回三個可比較對象的最大值

public class MaximumTest
{
   // 比較三個值并返回最大值
   public static <T extends Comparable<T>> T maximum(T x, T y, T z)
   {                     
      T max = x; // 假設x是初始最大值
      if ( y.compareTo( max ) > 0 ){
         max = y; //y 更大
      }
      if ( z.compareTo( max ) > 0 ){
         max = z; // 現(xiàn)在 z 更大 
      }
      return max; // 返回最大對象
   }
   public static void main( String args[] )
   {
      System.out.printf( "%d, %d 和 %d 中最大的數(shù)為 %d\n\n",
                   3, 4, 5, maximum( 3, 4, 5 ) );

      System.out.printf( "%.1f, %.1f 和 %.1f 中最大的數(shù)為 %.1f\n\n",
                   6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );

      System.out.printf( "%s, %s 和 %s 中最大的數(shù)為 %s\n","pear",
         "apple", "orange", maximum( "pear", "apple", "orange" ) );
   }
}

編譯運行以上 Java 代碼缭嫡,輸出結(jié)果如下

3, 4 和 5 中最大的數(shù)為 5
6.6, 8.8 和 7.7 中最大的數(shù)為 8.8
pear, apple 和 orange 中最大的數(shù)為 pear

泛型類

泛型類的聲明和非泛型類的聲明類似妇蛀,除了在類名后面添加了類型參數(shù)聲明部分

和泛型方法一樣笤成,泛型類的類型參數(shù)聲明部分也包含一個或多個類型參數(shù),參數(shù)間用逗號隔開

一個泛型參數(shù)纵诞,也被稱為一個類型變量浙芙,是用于指定一個泛型類型名稱的標識符

因為他們接受一個或多個參數(shù),這些類被稱為參數(shù)化的類或參數(shù)化的類型

下面的代碼演示了如何定義一個泛型類

public class Box<T> {

  private T t;

  public void add(T t) {
    this.t = t;
  }

  public T get() {
    return t;
  }

  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<Integer>();
    Box<String> stringBox = new Box<String>();

    integerBox.add(new Integer(10));
    stringBox.add(new String("簡單編程"));

    System.out.printf("整型值為 :%d\n\n", integerBox.get());
    System.out.printf("字符串為 :%s\n", stringBox.get());
  }
}

編譯運行以上代碼嗡呼,運行結(jié)果如下所示

整型值為 :10
字符串為 :簡單編程

類型通配符

  1. 類型通配符一般是使用 ? 代替具體的類型參數(shù)

    例如 List<?> 在邏輯上是 List<String>,List<Integer> 等所有 List<具體類型實參> 的父類

public class GenericTest {

        public static void main(String[] args) {
            List<String> name = new ArrayList<String>();
            List<Integer> age = new ArrayList<Integer>();
            List<Number> number = new ArrayList<Number>();

            name.add("icon");
            age.add(18);
            number.add(314);

            getData(name);
            getData(age);
            getData(number);

       }

       public static void getData(List<?> data) {
          System.out.println("data :" + data.get(0));
       }
    }
編譯運行以上 Java 代碼晤锥,輸出結(jié)果如下

data :icon
data :18
data :314

getDate() 方法的參數(shù)是 <List> 類型的矾瘾,所以 name,age蛉迹,number 都可以作為這個方法的實參放妈,這就是通配符的作用
  1. 類型通配符上限通過形如 List extends <Number>來定義

    如此定義就是通配符泛型值接受Number及其下層子類類型

public class GenericTest {

        public static void main(String[] args) {
            List<String> name = new ArrayList<String>();
            List<Integer> age = new ArrayList<Integer>();
            List<Number> number = new ArrayList<Number>();

            name.add("icon");
            age.add(18);
            number.add(314);

            //getUperNumber(name);//1
            getUperNumber(age);//2
            getUperNumber(number);//3

       }

       public static void getData(List<?> data) {
          System.out.println("data :" + data.get(0));
       }

       public static void getUperNumber(List<? extends Number> data) {
              System.out.println("data :" + data.get(0));
           }
    }
編譯運行以上 Java 代碼芜抒,輸出結(jié)果如下

data :18
data :314

在( //1 )處會出現(xiàn)錯誤,因為 getUperNumber()方法中的參數(shù)已經(jīng)限定了參數(shù)泛型上限為 Number攘宙,所以泛型為 String 是不在這個范圍之內(nèi)拐迁,所以會報錯

  1. 類型通配符下限通過形如 List<? super Number> 來定義

    表示類型只能接受 Number 及其三層父類類型,如 Objec 類型的實例

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铺韧,一起剝皮案震驚了整個濱河市缓淹,隨后出現(xiàn)的幾起案子讯壶,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丙挽,死亡現(xiàn)場離奇詭異匀借,居然都是意外死亡,警方通過查閱死者的電腦和手機吓肋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門肤舞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人李剖,你說我怎么就攤上這事∨忌郑” “怎么了德玫?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長材彪。 經(jīng)常有香客問我撒桨,道長,這世上最難降的妖魔是什么穗泵? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任谜疤,我火速辦了婚禮,結(jié)果婚禮上履肃,老公的妹妹穿的比我還像新娘尺棋。我一直安慰自己,他們只是感情好膘螟,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布荆残。 她就那樣靜靜地躺著净当,像睡著了一般内斯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上潭苞,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天萄传,我揣著相機與錄音蜜猾,去河邊找鬼。 笑死衍菱,一個胖子當著我的面吹牛肩豁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播琼锋,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼缕坎,長吁一口氣:“原來是場噩夢啊……” “哼篡悟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起荷腊,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤女仰,失蹤者是張志新(化名)和其女友劉穎抡锈,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體企孩,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡袁稽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了歧沪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诊胞。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡锹杈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邪码,到底是詐尸還是另有隱情咬清,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布影钉,位于F島的核電站掘剪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肆汹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一予权、第九天 我趴在偏房一處隱蔽的房頂上張望昂勉。 院中可真熱鬧,春花似錦扫腺、人聲如沸岗照。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽攒至。三九已至,卻和暖如春躁劣,著一層夾襖步出監(jiān)牢的瞬間迫吐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工账忘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留志膀,地道東北人熙宇。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓溉浙,卻偏偏與公主長得像戳稽,于是被迫代替她去往敵國和親惊奇。 傳聞我的和親對象是個殘疾皇子吨铸,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

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

  • 開發(fā)人員在使用泛型的時候竭缝,很容易根據(jù)自己的直覺而犯一些錯誤咙俩。比如一個方法如果接收List作為形式參數(shù)阿趁,那么如果嘗試...
    時待吾閱讀 1,045評論 0 3
  • 參考地址:《Java 泛型,你了解類型擦除嗎命黔?》 《Java中的逆變與協(xié)變》 《java 泛型中 T悍募、E .....
    琦小蝦閱讀 2,978評論 0 10
  • Java 泛型是 Java 5 引入的一個重要特性,相信大多數(shù) Java 開發(fā)者都對此不陌生喜鼓,但是泛型背后的實現(xiàn)原...
    JohnnyShieh閱讀 2,059評論 6 37
  • Java泛型總結(jié)# 泛型是什么## 從本質(zhì)上講膀懈,泛型就是參數(shù)化類型硼控。泛型十分重要牢撼,使用該特性可以創(chuàng)建類熏版、接口以及方...
    kylinxiang閱讀 911評論 0 1
  • 第六課第一次作業(yè): 設計三條主動添加好友的話術(shù)挺勿,話術(shù)里要包含:問好禾嫉,自我介紹蚊丐,提供價值麦备,暢銷泥兰,促使行動膀捷。以及每條話...
    李政達私域流量閱讀 119評論 0 0