Java 泛型

為什么使用泛型

泛型就是“參數(shù)化類型”完残,就是把類型當(dāng)作參數(shù)傳遞

對于為什么要使用泛型,我們先來舉幾個栗子

??1:

    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }

上面兩個方法的方法體實(shí)現(xiàn)都是一樣的均函,但是因?yàn)閰?shù)的類型和返回值的類型不同就需要定義兩個方法口予。

??2:

    public class MainActivity extends AppCompatActivity{
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initViews();
        initData();
      }
    }

        public class TestActivity extends AppCompatActivity{
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initViews();
        initData();
      }
    }

上面兩個activity類中實(shí)現(xiàn)的方法是一樣的规求,但是由于屬于不同的頁面導(dǎo)致我們要實(shí)現(xiàn)多個重復(fù)的代碼意荤。

??3:

List list = new ArrayList();
list.add(1);
list.add("a");
System.out.println((String)list.get(0) + (String)list.get(1));

報(bào)錯:

 java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

在編譯過程中辩尊,List中的類型應(yīng)該是Object烟馅,強(qiáng)制類型轉(zhuǎn)換就有可能出錯说庭。

泛型的好處:

1、多種數(shù)據(jù)類型執(zhí)行相同的代碼

2郑趁、實(shí)例化時指定類型刊驴,不需要強(qiáng)制類型轉(zhuǎn)換

泛型類、泛型接口、泛型方法

泛型類:

public class T1<T>{}

泛型接口:

public interface T2<T>{}

泛型方法:

// 1. 普通泛型方法

// 1.1 方法調(diào)用時指定類型
public <T> T test1(T t){
  return t;
} 

// 1.2 類初始化時指定類型
public class T1<T>{
  public T test1(T t){
    return t;
  }
}

// 2. 靜態(tài)泛型方法
public class T2<T>{
  
  // 此處的T和T2后面的T沒有任何關(guān)系捆憎,
  // T2中的T需要在初始化時指定類型舅柜,
  // 此處的靜態(tài)方法是在方法調(diào)用時指定的
  public static <T> T test(T t){
    return t;
  }
}

限定類型變量

有的時候,我們需要對類型變量(泛型)進(jìn)行約束攻礼,比如取兩個變量的最小值

public <T> T min(T a, T b) {
    if (a.compareTo(b) > 0) return b;
    else return a;
}

如何保證傳入的TcompareTo方法呢业踢?

public <T extends Comparable> T min(T a, T b) {
  if (a.compareTo(b) > 0) return b;
  else return a;
}

T extends Comparable & Serializable 泛型可以支持多個接口,如果限定類型有類礁扮,這個類必須是在限定列表的第一個知举。

泛型中的約束和局限性

  • 不能實(shí)例化基本數(shù)據(jù)類型的泛型

    // Test<double> t = new Test<double>();// 不允許這種寫法
    Test<Double> t = new Test<Double>();
    
  • 不能實(shí)例化類型變量

    // T t = new T();
    
  • 運(yùn)行時類型查詢,只能適用于原始類型

    Test<Double> t = new Test<>();
    //if(t instanceof Test<Double>) //不允許
    //if(t instanceof Test<T>) //不允許
    t.getClass();
    
  • 泛型類靜態(tài)上下文中類型變量失效

    class Test<T> {
      //此處的T和Test<T>不是同一個
      public static <T> T getInstance(){
        ...
      }
    }
    
  • 不能創(chuàng)建參數(shù)化類型的數(shù)組

    // Test<Double> ts = new Test<Double>[]; //不允許
    
  • 不能捕獲泛型類型的實(shí)例

    // class MyException<T> extends Exception //編譯器報(bào)錯
    // class MyThrowable<T> extends Throwable //編譯器報(bào)錯
    
    //public <T extends Throwable> void test(){
    //  try {
    //
    //  }catch (T e){//此處T報(bào)錯
    //
    //  }
    //}
    
    public <T extends Throwable> void test(){
      try {
    
      }catch (Throwable e){//可以這么寫
    
      }
    }
    

通配符類型

  • ? extends X

    表示類型的上界太伊,類型參數(shù)是X的子類

  • ? super X

    表示類型的下界雇锡,類型參數(shù)是X的超類

無限定的通配符

Pair<?>。初看起來僚焦,這好像與原始的 Pair 類型一樣锰提。 實(shí)際上, 有很大的不同芳悲。類型 Pair<?> 有以下方法:

? getFi rst() 
void setFirst(?)

getFirst 的返回值只能賦給一個 Object 立肘,setFirst 方法不能被調(diào)用, 甚至不能用 Object 調(diào)用名扛。Pair<?> 和 Pair 本質(zhì)的不同在于: 可以用任意 Object 對象調(diào)用原始 Pair 類的 setObject谅年;

為什么要使用這么脆弱的類型?

它對于許多簡單的操作非常有用肮韧。 例如融蹂, 下面這個方法 將用來測試一個 pair 是否包含一個 null 引用, 它不需要實(shí)際的類型弄企。

public static boolean hasNulls(Pair<?> p){
    return p.getFirstO = null || p.getSecondO = null;
}

也可以使用:

public static <T> boolean hasNulls(Pair<T> p)

但帶有通配符可讀性更強(qiáng)一些超燃。

虛擬機(jī)中是如何實(shí)現(xiàn)泛型的?

在Java語言處于還沒有出現(xiàn)泛型的版本時拘领,只能通過Object是所有類型的父類和類型強(qiáng)制轉(zhuǎn)換兩個特點(diǎn)的配合來實(shí)現(xiàn)類型泛化意乓。由于Java語言里面所有的類型都繼承于java.lang.Object,所以O(shè)bject轉(zhuǎn)型成任何對象都是有可能的约素。但是也因?yàn)橛袩o限的可能性洽瞬,就只有程序員和運(yùn)行期的虛擬機(jī)才知道這個Object到底是個什么類型的對象。在編譯期間业汰,編譯器無法檢查這個Object的強(qiáng)制轉(zhuǎn)型是否成功伙窃,如果僅僅依賴程序員去保障這項(xiàng)操作的正確性,許多ClassCastException的風(fēng)險就會轉(zhuǎn)嫁到程序運(yùn)行期之中样漆。

C#中的泛型和Java中的泛型有什么區(qū)別为障?

C#在編譯成中間語言時List<int>和List<String>是兩種不同的類型,而在Java中,泛型只是一種語法糖鳍怨,編譯成class文件后泛型就會被擦除呻右,變成List<Object>。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鞋喇,一起剝皮案震驚了整個濱河市声滥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侦香,老刑警劉巖落塑,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異罐韩,居然都是意外死亡憾赁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門散吵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來龙考,“玉大人,你說我怎么就攤上這事矾睦』蘅睿” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵枚冗,是天一觀的道長缓溅。 經(jīng)常有香客問我,道長官紫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任州藕,我火速辦了婚禮束世,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘床玻。我一直安慰自己毁涉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布锈死。 她就那樣靜靜地躺著贫堰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪待牵。 梳的紋絲不亂的頭發(fā)上其屏,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音缨该,去河邊找鬼偎行。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛤袒。 我是一名探鬼主播熄云,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼妙真!你這毒婦竟也來了缴允?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤珍德,失蹤者是張志新(化名)和其女友劉穎练般,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菱阵,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡踢俄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晴及。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片都办。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虑稼,靈堂內(nèi)的尸體忽然破棺而出琳钉,到底是詐尸還是另有隱情,我是刑警寧澤蛛倦,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布歌懒,位于F島的核電站,受9級特大地震影響溯壶,放射性物質(zhì)發(fā)生泄漏及皂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一且改、第九天 我趴在偏房一處隱蔽的房頂上張望验烧。 院中可真熱鬧,春花似錦又跛、人聲如沸碍拆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽感混。三九已至,卻和暖如春礼烈,著一層夾襖步出監(jiān)牢的瞬間弧满,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工此熬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谱秽,地道東北人洽蛀。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像疟赊,于是被迫代替她去往敵國和親郊供。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

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