编写泛型
# 泛型类
编写泛型类比普通类要复杂。通常来说,泛型类一般用在集合类中,例如ArrayList<T>
,我们很少需要编写泛型类。
如果我们确实需要编写一个泛型类,那么,应该如何编写它?
可以按照以下步骤来编写一个泛型类。
首先,按照某种类型,例如:String
,来编写类:
public class Pair {
private String first;
private String last;
public Pair(String first, String last) {
this.first = first;
this.last = last;
}
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
然后,标记所有的特定类型,这里是String
:
public class Pair {
private String first;
private String last;
public Pair(String first, String last) {
this.first = first;
this.last = last;
}
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
最后,把特定类型String
替换为T
,并申明<T>
:
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() {
return first;
}
public T getLast() {
return last;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
熟练后即可直接从T
开始编写。
# 静态方法
编写泛型类时,要特别注意,泛型类型<T>
不能用于静态方法的方法参数和返回值类型。
例如:
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() { ... }
public T getLast() { ... }
// 对静态方法使用<T>:
public static Pair<T> create(T first, T last) {
return new Pair<T>(first, last);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上述代码会导致编译错误,我们无法在静态方法create()
的方法参数和返回类型上使用泛型类型T
。
因为静态方法由于随着类的加载而加载,不能访问类的泛型(因为在创建对象的时候才确定),因此必须定义自己的泛型类型。
有些同学在网上搜索发现,可以在static
修饰符后面加一个<T>
,编译就能通过:
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() { ... }
public T getLast() { ... }
// 可以编译通过:
public static <T> Pair<T> create(T first, T last) {
return new Pair<T>(first, last);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
但实际上,这个<T>
和Pair<T>
类型的<T>
已经没有任何关系了。因为这是一个泛型方法。
泛型方法,可以声明为静态的。
因为:泛型参数是在调用方法时确定的。并非在实例化类时确定。
对于静态方法,我们可以单独改写为“泛型”方法,只需要使用另一个类型即可。
对于上面的create()
静态方法,我们应该把它改为另一种泛型类型,例如,<K>
:
public class Pair<T> {
private T first;
private T last;
public Pair(T first, T last) {
this.first = first;
this.last = last;
}
public T getFirst() { ... }
public T getLast() { ... }
// 静态泛型方法应该使用其他类型区分:
public static <K> Pair<K> create(K first, K last) {
return new Pair<K>(first, last);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这样才能清楚地将静态方法的泛型类型和实例类型的泛型类型区分开。
# 泛型方法
# 格式
[访问权限] <泛型> 返回类型方法名([泛型标识参数名称]) 抛出的异常
- 泛型方法声明泛型时也可以指定上限
public class DAO {
public <E> E get(int id, E e) {
E result= null;
return result;
}
}
2
3
4
5
6
dao:data(base) access object:数据访问对象。
# 多个泛型类型
泛型还可以定义多种类型。例如,我们希望Pair
不总是存储两个类型一样的对象,就可以使用类型<T, K>
:
public class Pair<T, K> {
private T first;
private K last;
public Pair(T first, K last) {
this.first = first;
this.last = last;
}
public T getFirst() { ... }
public K getLast() { ... }
}
2
3
4
5
6
7
8
9
10
使用的时候,需要指出两种类型:
Pair<String, Integer> p = new Pair<>("test", 123);
Java标准库的Map<K, V>
就是使用两种泛型类型的例子。它对Key使用一种类型,对Value使用另一种类型。
# 小结
编写泛型时,需要定义泛型类型<T>
;
静态方法不能引用泛型类型<T>
,必须定义其他类型(例如<K>
)来实现静态泛型方法;
泛型可以同时定义多种类型,例如Map<K, V>
。