Java泛型方法和建構函式


泛型方法

可以在方法宣告中定義型別引數,它們在方法的返回型別之前的尖括號中指定。包含泛型方法宣告的型別不必是通用型別。可以在非靜態方法宣告中使用為泛型型別指定的型別引數。

範例

以下程式碼顯示如何為方法m1()定義新的型別引數V。新型別引數V強制將方法m1()的第一個和第二個引數必須為相同型別。

第三個引數必須與型別T相同,這是類範例化的型別。

class MyBag<T> {
  private T ref;

  public MyBag(T ref) {
    this.ref = ref;
  }

  public T get() {
    return ref;
  }

  public void set(T a) {
    this.ref = a;
  }
}
class Test<T>  {
  public <V>  void  m1(MyBag<V>  a, MyBag<V>  b, T  c)  {

  }
}

使用通用方法

要傳遞方法的形式型別引數的實際型別引數,必須在方法呼叫中的點和方法名之間的尖括號<>中指定它。

class MyBag<T> {
  private T ref;

  public MyBag(T ref) {
    this.ref = ref;
  }

  public T get() {
    return ref;
  }

  public void set(T a) {
    this.ref = a;
  }
}
class Test<T> {
  public <V> void m1(MyBag<V> a, MyBag<V> b, T c) {
  }
}
public class Main {

  public static void main(String[] argv) {
    Test<String> t = new Test<String>();
    MyBag<Integer> iw1 = new MyBag<Integer>(new Integer(201));
    MyBag<Integer> iw2 = new MyBag<Integer>(new Integer(202));

    // Specify that Integer is the actual type for the type parameter for m1()
    t.<Integer>m1(iw1, iw2, "hello");

    t.m1(iw1, iw2, "hello");
  }
}

範例-2

以下程式碼顯示了如何宣告通用靜態方法。不能在靜態方法中參照包含類的型別引數。
靜態方法只能參照它自己宣告的型別引數。以下靜態通用型別定義了型別引數T,用於約束引數sourcedest的型別。

class MyBag<T> {
  private T ref;

  public MyBag(T ref) {
    this.ref = ref;
  }

  public T get() {
    return ref;
  }

  public void set(T a) {
    this.ref = a;
  }
}

public class Main {
  public static <T> void copy(MyBag<T> source, MyBag<? super T> dest) {
    T value = source.get();
    dest.set(value);
  }

  public static void main(String[] argv) {
  }
}

要為靜態方法呼叫指定實際的型別引數,可以這樣做:

Main.<Integer>copy(iw1, iw2);

通用建構函式

可以為建構函式定義型別引數。下面的程式碼定義了類Test的建構函式的型別引數U。它放置一個約束,建構函式的型別引數U必須是相同的,或者它的類型別引數T型別的子型別。

public class Test<T> {
  public <U extends T> Test(U k) {
  }
}

要為建構函式指定實際的型別引數值,請在 new 運算子和建構函式名稱之間的尖括號中指定它,如以下程式碼段所示:

class Test<T> {
  public <U extends T> Test(U k) {
  }
}

public class Main {
  public static void main(String[] argv) {
    // Specify the actual type parameter for the constructor as Double
    Test<Number> t1 = new<Double> Test<Number>(new Double(1.9));

    // Let the compiler figure out, Integer is
    // the actual type parameter for the constructor
    Test<Number> t2 = new Test<Number>(new Integer(1));

  }
}

通用物件在建立中的型別推斷

Java7在通用型別的物件建立表示式中增加了對型別推斷的一些有限支援。
對於以下語句:

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

Java7中,可以在上面的語句中指定空尖括號,稱為菱形操作符或簡單的菱形<>作為ArrayList的型別引數。

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

如果不在物件建立表示式中為通用型別指定型別引數,那麼型別是原始型別,編譯器生成未檢查的警告。
例如,以下語句將編譯產生未選中的警告:

List<String> list = new ArrayList(); // Generates an  unchecked  warning

不能建立通用的異常類。 並且沒有通用的匿名類。