泛型的基本介紹
阿新 • • 發佈:2018-12-08
1.為什麼需要泛型?泛型是什麼?
public class WhyGeneric {
public static void main(String[] args) {
List list = new ArrayList();
list.add("aaa");
list.add(111);
for (int i = 0; i < list.size(); i++) {
String s = (String) list.get(i);
System.out.println(s);
}
}
}
上面例子執行會報ClassCastException錯誤,list裡面放入了String和Integer型別的資料,編譯時不報錯,讀取執行時報錯,加上泛型在編譯時我們就不能給集合中新增兩種以以上型別的資料。
泛型是引數化的型別,在具體使用的過程中才會變成具體的型別。泛型的型別不可以是基本型別,只能是引用型別!
2.泛型擦除
@Test
public void caiChu() {
List<String> L1 = new ArrayList<String>();
List<Integer> L2 = new ArrayList<Integer>();
Class c1 = L1.getClass();
Class c2 = L2.getClass();
if(L1.equals(L2)) {
System.out.println("泛型擦除了");
}
}
輸出結果是“泛型擦除了”,證明在位元組碼中泛型就消失了。
3.泛型的使用:
* 泛型類
/**
* Created by Alsidun on 2018/7/12.
* 泛型類
*/
public class Generic<T> {
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey() {
return key;
}
}
public class TestGenericClass {
public static void main(String[] args) {
Generic<String> gs = new Generic<String>("abc");
Generic<Integer> gi = new Generic<>(1);
System.out.println("傳入的引數是 " + gs.getKey());
System.out.println("傳入的引數是 " + gi.getKey());
//這裡不指定引數型別,那麼就是Object
Generic ga = new Generic(1);
Generic gb = new Generic(1.5555);
Generic gc = new Generic(false);
System.out.println("傳入的引數是 " + ga.getKey());
System.out.println("傳入的引數是 " + gb.getKey());
System.out.println("傳入的引數是 " + gc.getKey());
}
}
/*
傳入的引數是 abc
傳入的引數是 1
傳入的引數是 1
傳入的引數是 1.5555
*/
上面的例子定義了一個泛型類及它的使用,只有在類例項化時才知道這個類的具體成員引數型別
- 泛型介面
/**
* Created by Alsidun on 2018/7/12.
*/
public interface GenericIntface<T> {
T say();
}
/**
* 未傳入泛型實參時,與泛型類的定義相同,在宣告類的時候,需將泛型的宣告也一起加到類中
* AnimalGeneric implements GenericIntface<T> 報錯!!!
* @param <T>
*/
class GenericImpl<T> implements GenericIntface<T> {
@Override
public T say() {
return null;
}
}
/**
* 在實現類實現泛型介面時,如已將泛型型別傳入實參型別,則所有使用泛型的地方都要替換成傳入的實參型別
*/
class AnimalGeneric implements GenericIntface<String> {
private String[] animal = new String[]{"dog", "cat", "pig"};
@Override
public String say() {
System.out.println("輸出狗 " + animal[0]);
return animal[1];
}
public static void main(String[] args) {
AnimalGeneric ag = new AnimalGeneric();
ag.say();
}
}
- 泛型方法
泛型方法是指在呼叫方法的時候在指明方法的引數型別
public <T> T show(Generic<T> container)
/**
* Created by Alsidun on 2018/7/12.
* 泛型方法
*/
public class GenericFruit {
static class Fruit {
@Override
public String toString(){
return "fruit";
}
}
static class Apple extends Fruit {
@Override
public String toString() {
return "apple";
}
}
static class Animal {
@Override
public String toString() {
return "person";
}
}
static class GenericTest<T> {
public void show1(T t) {
System.out.println("輸出 " + t.toString());
}
//此處的泛型可以和泛型類相同也可不同
public <T> void show2(T t) {
System.out.println("輸出 " + t.toString());
}
public <E> void show3(E t) {
System.out.println("輸出 " + t.toString());
}
}
public static void main(String[] args) {
/*成員方法,變數,內部類同一級別,必須通過類的例項呼叫
* 靜態方法裡面不可以訪問外部類的非靜態變數,普通內部類(都是靜態才可訪問)
* 靜態訪問靜態
* */
Apple apple = new Apple();
Animal animal = new Animal();
GenericTest<String> gs = new GenericTest<String>();
GenericTest<Fruit> gf = new GenericTest<Fruit>();
gs.show1("abc");
gf.show1(apple);
//gf.show1(animal); 無法編譯通過
gf.show2(apple);
gf.show2("qwe");
gf.show2(animal);
gf.show3(apple);
gf.show3(animal);
}
}
這裡會輸出對應的物件
4.泛型的萬用字元
使用時不知道型別使用萬用字元
ArrayList<?>
代表Object
ArrayList<? extends List>
List及其子類
ArrayList<? super List>
List及其父類