java泛型探索——泛型类

时间:2022-12-16 19:23:07

本文主要讨论一下如何声明泛型类,讨论的范围涉及构造函数、静态成员、内部类。

构造函数

泛型的类型参数首先声明在首部:

public class Pair<T,U> {
private final T first;
private final U second;
private static int count = 0;

public Pair(T first, U second) {
this.first = first;
this.second = second;
}

public T getFirst() {
return first;
}

public U getSecond() {
return second;
}

public static void main(String[] args) {
Pair<Integer,String> pair
= new Pair<Integer,String>(2,"generic test"); // 1 line
System.out.println(pair.getFirst());
System.out.println(pair.getSecond());
}
}

当我们调用构造函数时,真实的泛型参数将被传入,如代码中的“1 line”这行所示。

Pair<String, Integer> pair = new Pair("one",2); 

构造函数也可以向上述这么写,但会提示warning。

甚至我们还可以这么写:

Pair pair = new Pair("one",2); 

这个不会报错,也会提示warning。

静态成员

对于静态成员而言,是类可见的,所以 

public class Cell<T> {
private final int id;
private final T value;
private static int count = 0;
private static synchronized int nextId() {
return count++;
}

public Cell(T value) {
this.value = value;
id
= nextId();
}

public T getValue() {
return value;
}

public int getId() {
return id;
}

public static synchronized int getCount() {
return count;
}
}

我们可以通过Cell.getCount()直接获取静态成员,并不需要指定类型参数。

如果指定类型参数反而报错:

Cell<Integer>.getCount()   // compile-time error

泛型类的静态成员及静态函数是对整个泛型类而言,因此固定类型参数的类进行调用:如Cell<Integer>.getCount()。

同样的,像下面这样的代码也是错误的

class Cell2<T> {
private final T value;
private static List<T> values = new ArrayList<T>(); // illegal public Cell(T value) { this.value=value; values.add(value); } public T getValue() { return value; }
public static List<T> getValues() { return values; } // illegal
}

内部类

对非静态内部类而言,其外部类(outer class)的类型参数对它是可见的。因此内部类可以使用外部类的类型参数:

public class LinkedCollection<E> extends AbstractCollection<E> {     
private class Node {
private E element;
private Node next = null;
private Node(E elt) { element = elt; }
}
....
}

而对于静态内部类而言,则类型参数则是不可见的,我们必须自己定义内部类的类型参数:

class LinkedCollection<E> extends AbstractCollection<E> { 
private static class Node<T> {
private T element;
private Node<T> next = null;
private Node(T elt) { element = elt; }
}
}

我们在使用外部类中,使用内部类变量时,将外部类类型参数E传入内部类即可:

class LinkedCollection<E> extends AbstractCollection<E> { 
private static class Node<T> {
....
}
private Node<E> first = new Node<E>(null);
private Node<E> last = first;
}

在软件工程中,比较推荐使用静态内部类,因为它不持有外部类的引用。因此静态内部类可以像类似外部类一样使用,更简单,更好理解。

tips:

如果内部类的的修饰符是public

对非静态内部类而言,可以这么访问Node:LinkedCollection<E>.Node 

而对静态内部类而言:LinkedCollection.Node<E>。