泛型
- 编写的代码可以被很多不同类型的对象所重用
- 特定场合下,需要对类型进行限定(使用某些特定方法)
public class Test {
public static <T extends Comparable> T getMin(T... arr) {
if (arr == null || arr.length == 0) {
return null;
}
T min = arr[0];
for (T element : arr) {
min = (min.compareTo(element) > 0) ? element : min;
}
return min;
}
public static void main(String[] args) {
Integer[] arr = new Integer[]{6, 5, 4, 9, 8, 7};
System.out.println(Test.<Integer>getMin(arr));
}
}
泛型限定
- <T extends Comparable> 约定T必须是Comparable的子类
- extends固定,后面可以多个,以&拼接,如<T extends Comparable & Serializable>
- extends限定可以有多个接口,但只能一个类,且类必须排第一位
- 逗号隔参数,<T extends File & Cloneable, U extends Serializable>
泛型类之间的继承
- Pair<S>和Pair<T>没有任何关系,无论S和T之间是什么关系
- 泛型类可以扩展或实现其他的类,如ArrayList<T> 实现List<T>
上限界定符: Pair<? extends S>
- Pair能接收的参数类型,是S自身或子类
- Pair<? extends Fruit>代表Pair<Fruit>, Pair<Apple>, Pair<Orange> 等
Pair<? extends S>: Pair能接收的参数类型,是S自身或子类
- 只能get/不能set,编译器只能保证出来的类型,但不保证放入的对象是什么类型
- Pair<? extends Fruit>代表Pair<Fruit>, Pair<Apple>, Pair<Orange> 等
- ? extends Fruit getFirst(); // 调用子类方法,肯定可以转型到Fruit
- void setFirst(? extends Fruit) // 调用子类方法,入参必须是子类或孙类。但实际未知,故错误
class Fruit {
public String myClass = "Fruit";
public String getMyClass() {
return "Fruit";
}
}
class Apple extends Fruit {
public String myClass = "Apple";
@Override
public String getMyClass() {
return "Apple";
}
}
class Pair<T> {
T data;
Pair() {
}
Pair(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public class Test2 {
public static void main(String[] args) {
Pair<? extends Fruit> myPair = new Pair<>(new Apple());
System.out.println(myPair.getData().myClass);
System.out.println(myPair.getData().getMyClass());
}
}
下限界定符: Pair<? super S>
- Pair能接收的类型参数,是S的自身或超类
- Pair<? super Apple> 代表Pair<Object>, Pair<Fruit>, Pair<Apple>等
Pair<? super S>: Pair能接收的类型参数,是S本身或超类
- 只能set/不能get,编译器保证放入的是S本身或超类,但不保证出来是什么具体类型
- Pair<? super Apple> 代表Pair<Object>, Pair<Fruit>, Pair<Apple>等
- void setFirst(? super Apple) // 可以放入Apple及子类对象
- ? super Apple getFirst() // 无法得知出来的对象类型,只能是Object
泛型PECS原则
- Producer Extends, Consumer Super
- 要从泛型类读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends,泛型类是生产者,通过get往外输出东西)
- 如果要向泛型类写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super,泛型类是消费者,通过set往内增加东西)
- 如果既想写入又想读出,那就不用通配符