java基礎複習-----泛型

mz♪發表於2020-11-01

泛型的定義和意義

  泛型的本質是引數化型別,提供了編譯時的安全檢測機制,允許程式在編譯時檢測非法的型別。
  使用泛型的好處就是
① 程式碼複用,多種資料型別執行相同的程式碼;
② 在編譯期就能夠檢查型別是否安全(只要編譯時期沒有警告,那麼執行時期就不會出現ClassCastException異常),同時所有強制性型別轉換都是自動和隱式進行的,提高了程式碼的安全性和重用性。

Java的泛型是偽泛型,這是因為Java在編譯期間,所有的泛型資訊都會被擦掉,這也就是通常所說型別擦除

一些常用的泛型標記:

泛型標記說明
T(Type)表示java的型別,包括基本的類和開發者自定義的類 ,比如T Object
E(Element)表示在集合中存放的元素,是在集合中使用的 ,比如List< E > list
K(Key)表示鍵,在儲存鍵值對的資料結構中使用,比如map中的key
V(Value)表示值,和K對應
N(Number)表示各種數值型別
表示不確定的java型別

泛型的使用

泛型類

泛型類就是把泛型定義在類上,只有在使用該類的時候,才把型別明確下來。

/*
   把泛型定義在類上,型別變數定義在類上,方法中也可以使用
 */
public class ObjectTool<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

測試

public static void main(String[] args) {
        //建立物件並指定元素型別 String型別
        ObjectTool<String> tool = new ObjectTool<>();

        tool.setObj(new String("aaa"));
        String s = tool.getObj();
        System.out.println(s);

        //建立物件並指定元素型別 Integer型別
        ObjectTool<Integer> objectTool = new ObjectTool<>();
        /**
         * 如果我在這個物件裡傳入的是String型別的,它在編譯時就不會通過
         */
        objectTool.setObj(1);
        int i = objectTool.getObj();
        System.out.println(i);
    }

泛型方法

如果是僅僅需要某個方法使用泛型,那定義在類上就有點小題大做了,單獨給某個方法定義泛型,其他地方呼叫時就無需關注方法的返回型別。

	//定義泛型方法..
    public <T> void show(T t) {
        System.out.println(t);

    }

測試

public static void main(String[] args) {
        //建立物件
        ObjectTool tool = new ObjectTool();

        //呼叫方法,傳入的引數是什麼型別,返回值就是什麼型別
        tool.show("hello");
        tool.show(2);
        tool.show(2.11);
    }

泛型介面

/*
    把泛型定義在介面上
 */
public interface Inter<T> {
    public abstract void show(T t);

}

子類明確泛型類的型別引數變數

/**
	實現介面,重寫方法
 * 子類明確泛型類的型別引數變數:String
 */

public class InterImpl implements Inter<String> {
    @Override
    public void show(String s) {
        System.out.println(s);
    }
}

測試

//這時候只能是String
 Inter<String> a = new InterImpl();
 i.show("hello");
  • 子類不明確泛型類的型別引數變數:
/**
 * 子類不明確泛型類的型別引數變數:
 *      實現類也要定義出<T>型別的
 */
public class InterImpl<T> implements Inter<T> {
    @Override
    public void show(T t) {
        System.out.println(t);

    }
}

測試


public class InterImpl<T> implements Inter<T> {

    @Override
    public void show(T t) {
        System.out.println(t);
    }
}
//這個時候可以是String可以是Integer等等
 Inter<String> i1 = new InterImpl<>();
   i2.show("11");
   
 Inter<Integer> i2 = new InterImpl<>();
   i2.show(11);

限定泛型型別變數

  1. 對泛型上限的限定

   在Java中使用萬用字元“? ”和“extends”關鍵字指定泛型的上限,具體用法為<? extends T>,它表示該萬用字元所代表的型別是T類的子類或者介面T的子介面。

  1. 對泛型下限的限定

   在Java中使用萬用字元“? ”和“super”關鍵字指定泛型的下限,具體用法為<? super T>,它表示該萬用字元所代表的型別是T型別的父類或者父介面。

型別擦除

  在編碼階段採用泛型時加上的型別引數,會被編譯器在編譯時去掉,這個過程就被稱為型別擦除。因此,泛型主要用於編譯階段。在編譯後生成的Java位元組程式碼檔案中不包含泛型中的型別資訊。例如,編碼時定義的List和List在經過編譯後統一為List。JVM所讀取的只是List,由泛型附加的型別資訊對JVM來說是不可見的。Java型別的擦除過程為:首先,查詢用來替換型別引數的具體類(該具體類一般為Object),如果指定了型別引數的上界,則以該上界作為替換時的具體類;然後,把程式碼中的型別引數都替換為具體的類。

相關文章