1. 例如对于 Pair<T extends Comparable> 或者
public static <T extends Object & Comparable<? super T>> T min(List<T> list),可以调用Class,Field, Method的getTypeParameters函数来获取泛型信息,而对于有继承关系的,例如 DateInternel extends Pair<Date>, 可以用Class对象的getGenericSuperclass或者getGenericInterfaces来获取泛型的类型。
2. 一般对泛型我们会讲到一个擦除问题。主要表现在子类显示覆盖父类某个方法后,会造成在子类中会出现两个参数类型不同的方法,一个是泛型类型擦除后的方法,而一个是子类中指定类型的方法,例如
public class DateInternel extends Pair<Date> {
public Date getSecond() {
return super.getSecond();
}
public void setSecond(Date second) {
if(second.compareTo(getFirst())>=0)
super.setSecond(second);
}
}
当编译完成后,DateInternel类会从父类Pair继承到下面两个方法
public Comparable getSecond() {...}
public void setSecond(Comparable second) {...}
对于get函数,返回值是无法作为函数标识的,这样会有函数同名的错误,而对于set函数,会导致当对DateInternel实例对象调用setSecond(Date second)和setSecond(Comparable second)的结果完全不同,针对这种情况,编译器会产生两个桥接方法来处理。
// Method descriptor #14 (Ljava/lang/Comparable;)V
// Stack: 2, Locals: 2
public bridge synthetic void setSecond(java.lang.Comparable arg0);
0 aload_0 [this]
1 aload_1 [arg0]
2 checkcast java.util.Date [31]
5 invokevirtual com.statestreet.sle.chris.corejava.generic.DateInternel.setSecond(java.util.Date) : void [15]
8 return
Line numbers:
[pc: 0, line: 1]
// Method descriptor #30 ()Ljava/lang/Comparable;
// Stack: 1, Locals: 1
public bridge synthetic java.lang.Comparable getSecond();
0 aload_0 [this]
1 invokevirtual com.statestreet.sle.chris.corejava.generic.DateInternel.getSecond() : java.util.Date [81]
4 areturn
Line numbers:
[pc: 0, line: 1]
桥接代码的大概形式如上,保证了在子类实例函数调用的结果一致性。
bridge方法的解释:bridge method may be created by the compiler when extending a parameterized type whose methods have parameterized arguments.
Synthetic关键字的解释:A class member that does not appear in the source code must be marked using a Synthetic attribute." Also, "The Synthetic attribute was introduced in JDK release 1.1 to support nested classes and interfaces ."
3.对于下面两个实例对象,他们的Class对象是同一对象。
Pair<Date> datePair = new Pair<Date>();
Pair<String> stringPair = new Pair<String>();
datePair.getClass()==stringPair.getClass()
4.泛型不能用于catch block中,例如
public <T> T handle(List<T> list) {
try {
...
} catch(T t) {...}
}
编译器会提示错误。
5.不能创建泛型数组,例如 Pair<Date> pairs = new Pair<Date>[10];
6.不能实例化泛型变量和获取泛型的类信息, 例如 new T() 或者 T.class
7.类中声明的泛型类型不能用于静态变量和静态方法,会有编译错误,例如
public class Pair<T> {
public static T t;
public static Pair<T> getInstance() {...}
}
8.泛型的继承规则,Employee和Manager是父类和子类,但是Pair<Employee>和Pair<Manager>没有任何关系。