1. 程式人生 > 其它 >二分查詢 & 網線切割

二分查詢 & 網線切割

目錄

泛型(generics)

前言

出現的原因:想讓一個類可以用於所有型別,但是我們在以前定義的時候,只能定義一種型別,於是就出現了泛型。

泛型使用

我們可以看看 Java 定義的 List 介面的使用。

import java.util.ArrayList;
import java.util.List;

public class GenericTest {
    public static void main(String[] args) {
        // 指定型別 ,list 只能儲存 String 元素,告訴 Java 這個 List 只能有 String 元素
        List<String> strList = new ArrayList<>();
        strList.add("str1");
        strList.add("str2");
        strList.add("str3");
        strList.forEach(System.out::println);
    }
}

上面的 List 的引用指向的是 ArrayList 物件,我們看一下 ArrayList 中的 add 方法定義。

看一下 ArrayList 的 add 方法

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

可以看到要新增的元素型別是 E,那麼這個 E 來自哪裡呢?我們看一下 ArrayList 的定義:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

我們建立物件時是這樣的:

List<String> strList = new ArrayList<>();

也就是說,這個 E 就是我們在建立 ArrayList 物件時放入的型別,通過看 add 方法我們發現,要新增的元素也必須是這個型別。

當然別的類不一定是這樣,要根據泛型的定義來判斷使用的方式,具體情況,具體分析。

如何定義一個泛型

將型別定義在類後面的尖括號 ,可以定義多個。

public class MyGenericType1<MyType1, MyType2> {
    private MyType1 type1;
    private MyType2 type2;   
}

其實泛型就是型別擦除,然後在呼叫的時候,幫我們做強制型別轉換。如果出現錯誤,報錯資訊會顯示在呼叫的那一行

協變和逆變

協變和逆變都是針對引用型別的,不能用於建立物件型別,在建立物件時必須指定一個明確型別。

協變
List<? extends Person> persons = null;

這種形式就是協變,使用協變時,類必須是 ? extends 後面的類本身或其子類。

逆變
List<? super Student> person2s = null;

這種形式就是逆變,使用逆變時,類必須是? super 後面的類本身或其父類。


import java.util.ArrayList;
import java.util.List;

public class GenericTest {
    public static void main(String[] args) {
        // 指定型別 ,list 只能儲存 String 元素,告訴 Java 這個 List 只能有 String 元素
      //  協變:類必須是 ? extends 後面的類本身或其子類
        List<? extends Person> persons = null;
        // 不可以加入(List並沒有記住是什麼型別,需要指定明確的型別)
//        persons.add(new Person());
//        persons.add(new Student());
        persons = new ArrayList<Person>();
        persons = new ArrayList<Student>();

        // 逆變:類必須是 ? super 後面的類本身或者其父類類
        List<? super Student> person2s = null;
        person2s = new ArrayList<Person>();
        person2s = new ArrayList<Student>();

    }
}

寫入使用逆變,讀取使用協變。可以參考 Java 類庫中的方法。

泛型總結

泛型最重要的就是這兩點。

  • 編譯器檢查並進行型別擦除。
  • 使用時會進行型別強制轉換。