1. 程式人生 > >java 自定義泛型總結

java 自定義泛型總結

1、泛型

泛型就是引數化型別

  • 適用於多種資料型別執行相同的程式碼
  • 泛型中的型別在使用時指定
  • 泛型歸根到底就是“模版”

優點:使用泛型時,在實際使用之前型別就已經確定了,不需要強制型別轉換。

2、泛型類使用

泛型有三種使用方式,分別為:泛型類、泛型介面、泛型方法

2.1泛型類

  • 只能用在成員變數上,只能使用引用型別
  • 泛型型別用於類的定義中,被稱為泛型類。通過泛型可以完成對一組類的操作對外開放相同的介面。最典型的就是各種容器類,如:List、Set、Map。
//此處T可以隨便寫為任意標識,常見的如T、E、K、V等形式的引數常用於表示泛型
//在例項化泛型類時,必須指定T的具體型別
public class test<T>{ 
    //key這個成員變數的型別為T,T的型別由外部指定  
    private T key;

    public test(T key) { //泛型構造方法形參key的型別也為T,T的型別由外部指定
        this.key = key;
    }

    public T getKey(){ //泛型方法getKey的返回值型別為T,T的型別由外部指定
        return key;
    }
}

泛型類 

2.2泛型介面

  • 只能用在抽象方法上
/**
 * 自定義泛型介面
 *
 * 介面中泛型字母只能使用在方法中,不能使用在全域性常量中
 *
 * @param <T>
 */
public interface Comparator<T1,T2> {
  
  //public static final T1 MAX_VALUE = 100; //介面中泛型字母不能使用在全域性常量中
  //T1 MAX_VALUE;
  public static final int MAX_VALUE = 100;
  
  void compare(T2 t);
  T2 compare();
  public abstract T1 compare2(T2 t);
}

 

2.3泛型方法

在其返回值前加<T>

import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
 
 
/**
 * 非泛型類中定義泛型方法
 *
 */
public class Method {
 
  // 泛型方法,在返回型別前面使用泛型字母
  public static <T> void test1(T t){
    System.out.println(t);
  }
  
  // T 只能是list 或者list 的子類
  public static <T extends List> void test2(T t){
    t.add("aa");
  }
  
  // T... 可變引數   --->   T[]
  public static <T extends Closeable> void test3(T...a) {
    for (T temp : a) {
     try {
       if (null != temp) {
         temp.close();
       }
     } catch (Exception e) {
       e.printStackTrace();
     }
     
    }
  }
  
  public static void main(String[] args) throws FileNotFoundException {
    test1("java 是門好語言");
    test3(new FileInputStream("a.txt"));
  }
}

 

2.4 泛型的基本用法

public class GenericTest {
   //這個類是個泛型類,在上面已經介紹過
   public class Generic<T>{     
        private T key;

        public Generic(T key) {
            this.key = key;
        }

        //我想說的其實是這個,雖然在方法中使用了泛型,但是這並不是一個泛型方法。
        //這只是類中一個普通的成員方法,只不過他的返回值是在宣告泛型類已經宣告過的泛型。
        //所以在這個方法中才可以繼續使用 T 這個泛型。
        public T getKey(){
            return key;
        }

        /**
         * 這個方法顯然是有問題的,在編譯器會給我們提示這樣的錯誤資訊"cannot reslove symbol E"
         * 因為在類的宣告中並未宣告泛型E,所以在使用E做形參和返回值型別時,編譯器會無法識別。
        public E setKey(E key){
             this.key = keu
        }
        */
    }

    /** 
     * 這才是一個真正的泛型方法。
     * 首先在public與返回值之間的<T>必不可少,這表明這是一個泛型方法,並且聲明瞭一個泛型T
     * 這個T可以出現在這個泛型方法的任意位置.
     * 泛型的數量也可以為任意多個 
     *    如:public <T,K> K showKeyName(Generic<T> container){
     *        ...
     *        }
     */
    public <T> T showKeyName(Generic<T> container){
        System.out.println("container key :" + container.getKey());
        //當然這個例子舉的不太合適,只是為了說明泛型方法的特性。
        T test = container.getKey();
        return test;
    }

    //這也不是一個泛型方法,這就是一個普通的方法,只是使用了Generic<Number>這個泛型類做形參而已。
    public void showKeyValue1(Generic<Number> obj){
        Log.d("泛型測試","key value is " + obj.getKey());
    }

    //這也不是一個泛型方法,這也是一個普通的方法,只不過使用了泛型萬用字元?
    //同時這也印證了泛型萬用字元章節所描述的,?是一種型別實參,可以看做為Number等所有類的父類
    public void showKeyValue2(Generic<?> obj){
        Log.d("泛型測試","key value is " + obj.getKey());
    }

     /**
     * 這個方法是有問題的,編譯器會為我們提示錯誤資訊:"UnKnown class 'E' "
     * 雖然我們聲明瞭<T>,也表明了這是一個可以處理泛型的型別的泛型方法。
     * 但是隻聲明瞭泛型型別T,並未宣告泛型型別E,因此編譯器並不知道該如何處理E這個型別。
    public <T> T showKeyName(Generic<E> container){
        ...
    }  
    */

    /**
     * 這個方法也是有問題的,編譯器會為我們提示錯誤資訊:"UnKnown class 'T' "
     * 對於編譯器來說T這個型別並未專案中宣告過,因此編譯也不知道該如何編譯這個類。
     * 所以這也不是一個正確的泛型方法宣告。
    public void showkey(T genericObj){

    }
    */

    public static void main(String[] args) {


    }
}

2.5泛型方法的可變引數

public <T> void printMsg( T... args){
    for(T t : args){
        Log.d("泛型測試","t is " + t);
    }
}

printMsg("111111",12.22,123,false);

參考連結:https://www.cnblogs.com/coprince/p/8603492.html