今天复习泛型的时候看到这样一段代码
private static <T extends Number & Comparable<? super T>> T min(T[] values){ // 传入的实参类型必须是Number的子类,且实参或者实参的父类必须实现了 Comparable接口, if(values == null || values.length == 0){ return null; } T min = values[0]; for(int i = 1; i < values.length; i++){ if(min.compareTo(values[i]) > 0){ min = values[i]; } } return min; }
上面的泛型声明确实是十分复杂,<T extends Number & Comparable<? super T>其实是由下面两部分组成
<T extends Number>
<T extends Comparable<? super T>>
第一个泛型声明表示 实参类型必须是 Number 或者Number 的子类,这个比较好理解
第二个泛型声明表示 实参类型必须是 实现了Comparable 接口或者其父类实现了Comparable 接口,假设 Dog 类继承了 Animal 类,如果Animal 没有实现 Comparable 接口,但是Dog 类自己实现了,那么Dog 类可以作为这个函数的泛型类型实参,如果 Dog 没有直接实现 Comparable 接口,但是它的父类 Animal 实现了,Dog 类也可以作为泛型类型的实参,因为Dog 自己虽然没有 重写CompareTo()方法,但是它的父类重写了,它可以调用父类的Comparable 方法。说到这里应该很明白了如果用的是 <T extends Comparable<? super T>> 那么只要实参类型或实参类型的父类实现了 Comparable 接口,那 这个实参类型就可以用这个方法,而如果 用的是 <T extends Comparable<T>> 声明泛型的话,只有当实参类型实现了 Comparable 接口,他才可以使用这个方法,就算它的父类实现这个方法也不行。
如下面这段代码:虽然 MyNumberSon 类的父类 MyNumberFather 实现了 Comparable 接口,但是因为采用的是 <T extends Comparable<T>> 的泛型声明方式,所以 MyNumberSon 还是不能使用这个 min() 方法
class MyNumberFather extends Number implements Comparable<MyNumberFather>{ @Override public int compareTo(MyNumberFather o) { return 0; } @Override public int intValue() { return 0; } @Override public long longValue() { return 0; } @Override public float floatValue() { return 0; } @Override public double doubleValue() { return 0; } }
MyNumberSon 类
class MyNumberSon extends MyNumberFather{ @Override public int compareTo(MyNumberFather o) { return 0; } }
上面的 min() 函数将泛型声明做些改动,改成下面这种形式
private static <T extends Number & Comparable<T>> T min(T[] values){ if(values == null || values.length == 0){ return null; } T min = values[0]; for(int i = 1; i < values.length; i++){ if(min.compareTo(values[i]) > 0){ min = values[i]; } } return min; }
那么如果在主函数中调用 min (), 则会有编译错误
但是如果使用的 <T extends Comparable<? super T>> 则不会报错。
总结:
如果用的是 <T extends Comparable<? super T>> 那么只要实参类型或实参类型的父类实现了 Comparable 接口,那 这个实参类型就可以用这个方法,
而如果 用的是 <T extends Comparable<T>> 声明泛型的话,只有当实参类型实现了 Comparable 接口,他才可以使用这个方法,就算它的父类实现这个方法也不行。
<T extends Comparable<? Super T>> 相比于 <T extends Comparable<T>> 有更好的通用性。