建立泛型類

泛型使類,介面和方法能夠將其他類和介面作為型別引數。

此示例使用泛型類 Param 獲取單個型別引數 T,由尖括號(<>)分隔:

public class Param<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

要例項化此類,請提供型別引數來代替 T。例如,Integer

Param<Integer> integerParam = new Param<Integer>();

type 引數可以是任何引用型別,包括陣列和其他泛型型別:

Param<String[]> stringArrayParam;
Param<int[][]> int2dArrayParam;
Param<Param<Object>> objectNestedParam;

在 Java SE 7 及更高版本中,type 引數可以替換為名為 diamond 的 一組空型別引數(<>) :

Version >= Java SE 7

Param<Integer> integerParam = new Param<>();

與其他識別符號不同,型別引數沒有命名約束。然而,他們的名字通常是大寫的第一個字母。 (即使在官方 JavaDocs 中也是如此。)
例子包括 T 用於 typeE 用於 elementK / V 用於 key/value

擴充套件泛型類

public abstract class AbstractParam<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

AbstractParam 是一個使用 T 型別引數宣告的抽象類 。擴充套件此類時,該型別引數可以由 <> 中寫入的型別引數替換,或者型別引數可以保持不變。在下面的第一個和第二個例子中,StringInteger 替換了型別引數。在第三個示例中,型別引數保持不變。第四個例子根本不使用泛型,所以它類似於類有 Object 引數。編譯器會警告 AbstractParam 是一個原始型別,但它會編譯 ObjectParam 類。第五個示例有 2 個型別引數(請參閱下面的多個型別引數),選擇第二個引數作為傳遞給超類的型別引數。

public class Email extends AbstractParam<String> {
    // ...
}

public class Age extends AbstractParam<Integer> {
    // ...
}

public class Height<T> extends AbstractParam<T> {
    // ...
}

public class ObjectParam extends AbstractParam {
    // ...
}

public class MultiParam<T, E> extends AbstractParam<E> {
    // ...
}

以下是用法:

Email email = new Email();
email.setValue("test@example.com");
String retrievedEmail = email.getValue();

Age age = new Age();
age.setValue(25);
Integer retrievedAge = age.getValue();
int autounboxedAge = age.getValue();

Height<Integer> heightInInt = new Height<>();
heightInInt.setValue(125);

Height<Float> heightInFloat = new Height<>();
heightInFloat.setValue(120.3f);

MultiParam<String, Double> multiParam = new MultiParam<>();
multiParam.setValue(3.3);

請注意,在 Email 類中,T getValue() 方法的行為就像它具有 String getValue() 的簽名一樣,而 void setValue(T) 方法的行為就像它被宣告為 void setValue(String) 一樣。

也可以使用帶有空花括號的匿名內部類({})進行例項化:

AbstractParam<Double> height = new AbstractParam<Double>(){};
height.setValue(198.6);

請注意,不允許使用帶有匿名內部類的菱形。

多種型別引數

Java 提供了在泛型類或介面中使用多個型別引數的功能。通過在尖括號之間放置以逗號分隔的型別列表,可以在類或介面中使用多個型別引數。例:

public class MultiGenericParam<T, S> {
    private T firstParam;
    private S secondParam;
   
    public MultiGenericParam(T firstParam, S secondParam) {
        this.firstParam = firstParam;
        this.secondParam = secondParam;
    }
    
    public T getFirstParam() {
        return firstParam;
    }
    
    public void setFirstParam(T firstParam) {
        this.firstParam = firstParam;
    }
    
    public S getSecondParam() {
        return secondParam;
    }
    
    public void setSecondParam(S secondParam) {
        this.secondParam = secondParam;
    }
}

用法可以如下完成:

MultiGenericParam<String, String> aParam = new MultiGenericParam<String, String>("value1", "value2");
MultiGenericParam<Integer, Double> dayOfWeekDegrees = new MultiGenericParam<Integer, Double>(1, 2.6);