welcome to Tong's Digital Garden
bigguaiwutong@qq.com
Ref:Lesson: Generics
泛型的好处
泛型类型命名规范
Parameter VS argument Parameter: 声明的参数类型 Argument: 实际传入的参数 当调用一个方法时,我们传入的 argument 必须符合 parameter 的类型和顺序
<>
多个类型参数 参数化类型
前置信息:我们有一个如下的泛型类
public class Box<T> {
//...
}
为了创建一个参数化的 Box<T>,需要为形式类型参数(parameter)提供一个真正的参数(argument),如果省略了实际参数(argument),那么就是原始类型(raw types),非泛型类或接口没有 raw types
//etc
Box box = new Box();
在使用 raw types 时会绕过泛型类型检查,将不安全代码的捕获推迟到运行时,因此,我们要尽量避免使用 raw types
当将一个 raw types 的泛型类赋值给一个具体的泛型类时就会发生 unchecked error
//etc
Box<Integer> bi;
bi = new Box();
//将会提示如下 msg
warning:[unchecked] unchecked conversion
解决方案:
-Xlint:-unchecked 重新进行编译@SuppressWarnings("unchecked")泛型方法时引入自己的类型参数(parameters)的方法
在泛型方法语法中,在返回值中使用到的 type,需要在方法的入参中被定义(放在尖括号中),对于静态方法,类型参数必须出现在返回类型之前
//etc
public class Util {
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey);
}
}
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public void setKey(K key) { this.key = key; }
public void setValue(V value) { this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}
//对 compare 方法的使用
Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "banana");
boolean same = Util.<Integer, String>compare(p1, p2);
// 上一行 <Integer, String> 的声明可以去除,因为可以通过 type inference 进行自动匹配
//上一行可以简化为
boolean same = Util.compare(p1, p2);
//etc
public <U extends Integer> void inspect(U u) {
...
}
通过这种方式,传入不被允许的类型时,编译就会报错
//etc
public class NatualNumber<T extends Integer> {
privaye T n;
public NaturalNumber(T n) { this.n = n; }
public boolean isEven() {
return n.intValue % 2 == 0;
}
}
public class NatualNumber<T extends A & B & C> {
...
}
public static <T> int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray)
if (e > elem) // compiler error
++count;
return count;
}
这里编译失败的原因时因为 > 只适用于 short, int 等类型,但是我们可以通过限制 Comparable<T> 来实现
public interface Comparable<T> {
Public int compareTo (T o);
}
public static <T extends Comparable<T>> int countGreaterThan (T[] anArray, T elem) {
Int count = 0;
For (T e : anArray)
if (e.compareTo (elem) > 0)
++count;
Return count;
}

在泛型代码中,? 被称为通配符,用于表示未知类型,可以用于 parameter 但是不能用于 argument
public class A {
...
}
public class B extends A {
...
}
public class C extends A{
...
}
上界通配符可以放宽对变量的限制,使用 extends
public static void process(List<? extends A> list) {
//...
}
上面可以接受匹配 A 和 A 的任意子类型(A,B,C 类均可)
无界通配符使用 ? 进行指定,表示未知类型的列表。
Class<?> 经常会被分的 Class<T> 方法并依赖于 `T
将未知类型限制为特定类型或者该类型的父类型,使用
java
public static void process(List<? super B> list) {
//...
}
可以接受的类型为 B 和 A
假设一个方法 copy(src, dest) src 提供需要复制的数据,是 in 变量, dest 参数接受数据,是 out 变量
in 变量通常使用上界通配符进行定义out 变量通常使用下界通配符进行定义in 变量可以通过 Object 类中定义的方法访问,使用无界通配符