泛型类
泛型类的语法
- 声明泛型类:
class class-name<type-param-list> { }
- 创建泛型类实例:
class-name<type-arg-list> instance = new class-name<type-arg-list>(value-arg-list);
- JDK 7新增的类型推断(省略type-arg-list):
class-name<type-arg-list> instance = new class-name<>(value-arg-list);
一个类型参数的泛型类
// 声明
public class Generic<T> {
private T obj;
public Generic(T obj) {
this.obj = obj;
}
// ...
}
// 实例化
Generic<Integer> iInstance = new Generic<Integer>(100);
Generic<String> sInstance = new Generic<>("test"); // 类型推断
两个类型参数的泛型类
public class Generic<T, V> {
private T first;
private V second;
public Generic(T first, V second) {
this.first = first;
this.second = second;
}
// ...
}
Generic<Integer, String> instance = new Generic<Integer, String>(100, "test");
注意:
- 类型参数只能是引用类型,不能使用基本类型。比如下面的声明是非法的:
Generic<int> instance = new Generic<int>(100);
- 基于不同类型参数的泛型类型是不同的。比如下面的例子不能通过编译:
Generic<Integer> iInstance = new Generic<Integer>(100);
Generic<String> sInstance = new Generic<String>("test");
iInstance = sInstance;
类型边界
可以通过为类型参数声明超类来限定类型参数的边界。声明语法如下所示:
<T extends superclass>
这样就指定了T只能是superclass或其子类。
下面这个例子中sum()调用了Number类的doubleValue方法,如果不指定类型边界为Number,就会编译失败,提示doubleValue()方法是未知的。
public class Calculator<T extends Number> {
private T[] nums;
public Calculator(T[] nums) {
this.nums = nums;
}
public double sum() {
double s = 0.0;
for (T num : nums) {
s += num.doubleValue();
}
return s;
}
}
除了可以使用类作为边界,还可以指定接口作为边界,而且边界可以是一个类和一个或多个接口。类型参数必须同时满足超类和接口的限制才是合法的。例如:
public class Generic<T extends MyClass & MyInterface> { // ... }
泛型方法
泛型类中的方法可以使用类的类型参数,所以它们是自动相对于类型参数泛型化的。此外,在非泛型类中也可以创建泛型方法。
泛型方法的语法
- 声明泛型方法:
<type-param-list> return-type method-name(param-list) { }
- 声明泛型构造函数:
<type-param-list> construct-name(param-list) { }
泛型方法的例子
public <T extends Number> boolean check(T num) {
// ...
}
泛型构造函数的例子
public <T extends Number> Generic(T num) {
// ...
}
泛型接口
除了可以定义泛型类和泛型方法外,还可以定义泛型接口。
泛型接口的语法
- 声明泛型接口
interface interface-name<type-param-list> { }
- 实现泛型接口
class class-name<type-param-list> implements interface-name<type-arg-list> { }
例子
public interface MinMax<T extends Comparable<T>> {
T min();
T max();
}
public class MyClass<T extends Comparable<T>> implements MinMax<T> {
private T[] values;
// ...
}
注意:
- 泛型接口的实现类的类型参数必须指定和接口相同的边界。并且一旦指定了边界,就不需要再在implements子句中指定。比如下面的代码是错误的,不能通过编译:
public class MyClass<T extends Comparable<T>>
implements MinMax<T extends Comparable<T>> {
// ...
}
- 如果类实现了泛型接口,那么类也必须是泛型化的。比如下面的类声明是错误的:
public class MyClass implements MinMax<T> {
// ...
}
- 如果类实现了某种具体类型的泛型接口,那么实现类不需要是泛型化的。如下所示:
public class MyClass implements MinMax<Integer> {
// ...
}
网友评论