import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
public class Ans {
public static void main(String[] args) {
test3();
test6();
}
static void test0() {
//對於List<Inter>不能轉型爲List<Number>有一個理解,如果可以這麼做轉型後就可以add(new Float(0))這明顯不合適
}
static void test3() {
//在泛型中無法得到類型參數,但是如果有一個類繼承了含有確定類型參數的泛型,則可以從這個類得到父類的類型參數,因爲如果這時還沒有任何父類類型參數的信息,子類就不知道自己可以保存什麼樣的數據
class A<T> {}
class AInt extends A<Integer> {}
System.out.println(Arrays.toString(A.class.getTypeParameters())); //這裏的T只是個名字,毫無意義
System.out.println(AInt.class.getGenericSuperclass().getTypeName()); //這是類型參數的類名
System.out.println(Arrays.toString(((ParameterizedType) AInt.class.getGenericSuperclass()).getActualTypeArguments())); //這是這個類的class對象
}
static void test4() {
class A<T> {
void a(A<? extends T> a,T t) {} //對於這種傳參的一個優勢是可以保證a在方法中無法調用a.set(anything)這種方法,即限制了a的行爲,當然一個例外是a.set(null),這個可以使用,但多是情況下是無意義的
}
}
static void test5() {
//同樣的super也是爲了限制一些行爲
//無界通配符<?>的一個特點:A<?>可以接受一切A<>或A的向上轉型,而且它也可以限制很多操作
//而且使用無界通配A<?>符代替無通配符A的一個好處是可以將一些不合適的由警告變成編譯時報錯
}
static void test6() {
class B {}
B []b = pickTwo(new B(),new B());
}
static <K> K[] pickTwo(K k1,K k2) {
K []k = (K [])asArray(k1,k2); //這裏必須要轉型
K []k0 = asArray2(k1,k2);
//! return (K [])asArray(k1,k2); //這兩個都是classCastException,由於這個K[]不能傳遞到外界
//! return asArray2(k1,k2);
return null;
}
static Object[] asArray(Object o1,Object o2) {return new Object[]{o1,o2};}
static <T> T[] asArray2(T...objs) {return objs;}
}
class A<T> {
//! public boolean equals(T obj) {return super.equals(obj); } //這樣不行,因爲T被擦除爲Object,這樣就與Object.equals有相同的參數所以這不是一個重載,而這個表示又不是重寫
static void test2() {
//泛型類中的靜態方法不能使用類中的泛型參數,在下面我們可以看到方法可以含有泛型類型,但是這個T已經與類型中的T無關了,最好改一下名稱
}
//! static void a(T t){}
static <T> void a(T t) {} //這個T和類中的T無關,建議改成別的名字(如下)
static <K> void b(K k) {}
}