Java 泛型總結

2021-06-28 01:35:03 字數 4284 閱讀 8490

泛型指引數化型別的能力,可以定義帶泛型型別的類或方法,隨後編譯器會用具體的型別來替換它。

在泛型產生之前,像集合的訪問都是靠強制型別轉換:

public class arraylist 

public void add(object o)

...}

string filename = (string) names.get(0);
這樣沒有進行錯誤檢查,在執行時可能發生型別轉換錯誤,程式設計時必須小心。

泛型提供了型別引數,放在一對尖括號中。像這樣被稱為 形式泛型型別(formal generic type),隨後可以用乙個實際具體型別(actual concrete type)來替換,這個過程叫泛型例項化(generic instantiation)。

arraylistnames = new arraylist();
型別引數string說明了list中只存放string物件,當呼叫get的時,不需要手動進行型別轉換,編譯器會幫我們完成這個過程,並返回string。當呼叫add時,編譯器會進行檢查,傳入非string型別的引數,編譯不能通過。

泛型的加入,使得能夠在編譯時而不是在執行時檢測出型別錯誤。提高**的可靠性和可讀性。

注意, 泛型必須是引用型別,不能是基本型別,int, double這種需要用integer,double等替換。

泛型類: 定義乙個類為泛型型別,需要將型別引數放在類名之後。

public class pair

public void setfirst(t first)

public t getsecond()

public void setsecond(t second)

}

型別引數命名規則:e-集合,k-key,v-value,t-任意型別。

泛型方法:泛型方法既可以定義在普通類中,也可以定義在泛型類中。

定義乙個方法為泛型型別,需要將型別引數放在方法返回型別之前:

public static t getmiddle(t a)
呼叫這個方法:

public class test ;

string middle = test.getmiddle(names);

} ...

型別引數也可以省略:

public class test ;

string middle = getmiddle(names);

} ...

型別變數的限定:

將泛型指定為另外一種泛型的子型別,這種泛型型別稱為受限泛型(bounded)

t和繫結型別可以是類,也可以是介面。

乙個型別變數或者萬用字元可以有多個限定:

t extends comparable & serializable    

&分隔限定型別,逗號分隔型別變數:

public class interval

public void setfirst(object first)

public object getsecond()

public void setsecond(object second)

}

因為t沒有限定型別,所以用object替換。

另乙個例子:

public class interval else 

}}

型別擦除後:

public class interval  else 

}}

如果調換comparable 和serializable的順序,原始型別會用serializable替換t,在方法體內會執行comparable  的強制型別轉換,所以為了提高效率,一般應該將沒有方法的介面放在最後。

方法的型別擦除:

public static t min(t a)
擦除後:

public static comparable min(comparable a)

如果乙個方法的返回型別是泛型變數,由於進行了型別擦除,在呼叫這個方法後,返回值會被進行型別強制轉換:

pairp = ...

employee e = p.getfirst();

擦除getfirst返回型別後將返回object型別,虛擬機會進行強制型別轉換,以上語句,會被翻譯為2條虛擬機器指令:

1.對原始方法getfrist的呼叫

2.將返回的oject型別強制轉換為employee型別

通配泛型型別:

? extends t : 受限通配

現有方法 print輸出employee 的姓名:

public class employee 

public void setname(string name)

@override

public string tostring()

}

public class manager extends employee
public class test 

public static void print(pairp)

}

儘管manager 是employee的子類,但是不能這樣呼叫:

pairp2 = new pair();

print(p2); //編譯不過

這時需要使用萬用字元,

public static void print(pair<? extends employee> p)

輸出: tim and hank

注意: employee first = p.getfirst();可以正常呼叫,但是setfirst引數不能傳入 employee的例項,而只能傳入manager的例項。

因為型別引數是<? extends employee>編譯器只知道是 employee的子型別,父類引用子類是合法的,所以可以將getfirst的返回值賦給乙個employee物件,而employee子類不包含employee本身,所以在set方法中不能傳入employee的例項。

? super t : 下限通配:

? super manager 這個萬用字元限制為manager及其所有超型別。

這個萬用字元的行為和上面相反,它可以使用manager作為方法的引數,但是不能使用返回值:

pairp3 = new pair();

p3.setfirst(manager);

p3.setsecond(manager2);

print2(p3);

public static void print2(pair<? super manager> p)
注意這裡 p.getfirst()返回的是object物件,因為 ? super manager,編譯器只知道是 manager的超類,並不知道具體的類。這段**只是為了說明問題,實際上是不合適的。

實際應用舉例:根據提供的manager陣列引數,提供排序後的pair物件。

public static void minmax (manager a, pair<? super manager> result) 

manager min = a[0];

manager max = a[0];

for (int i = 0; i < a.length; i++)

if (max.getname().compareto(a[i].getname()) < 0)

} result.setfirst(min);

result.setsecond(max);

}

簡單說就是,下限通配可以寫入,受限通配可以讀取。

?:無限定通配:

像pair<?> 這樣的?萬用字元叫做無限定通配,使用它不需要知道實際的型別:

public boolean hasnulls(pair<?> p)
無限定萬用字元也可以用具體型別變數替代:

public boolean hasnulls2(pairp)
但是前者的可讀性更強。

Java泛型總結

1 泛型主要是用來年解決資料型別安全的問題,用標識來代替屬性的型別或者返回值的型別 2 在使用泛型的時候可以有以下幾種形式 泛型介面 泛型類 萬用字元做泛型引數 泛型方法 泛型陣列 3 以下通過 說明 package com.sun.demo 一 定義泛型介面 inte ce father 二 定義...

java泛型總結

1.概念 泛型實現了引數化型別的概念,其最初的目的是希望類或方法能夠具備最廣泛的表達能力。通俗來說就是為了避免轉換出錯,限制資料型別。通過解耦類或者方法與所使用的型別之間的約束。list thelist1 new arraylist arrays.aslist 1,2,3,string for ob...

java泛型總結

提高 的復用性 1.泛型類 package xinceshi class box public t get public class iotest 2.泛型函式class util 呼叫的時候和呼叫普通函式一樣,不用加尖括號 3.邊界符public static int greaterthan t ...