第一段代码出错,容易理解,因为JAVA 方法的重载,基本要求是方法签名不同,而我们学习到的方法签名包含方法名及参数类型,个数,及顺序。因为泛型使用了擦除法,所以编译后两个方法签名一致。但为什么第二个通过了呢,返回值并不在代码签名范围啊。可以自己做个试验,不使用泛型类参数,只使用不同的返回值重载一个方法,也通不过。
其实原因就是使用擦除法的缺点。因为如果不是使用擦拭法,如C#,List 和List 是两个不同的类型,可以重载。而使用擦除法后,为了实现重载只能增加一个可能没必要的返回值作为签名的一部分。具体实现可以去看看java 规范。
泛型的定义和使用比较简单,以代码代替说教了。
/*
* 定义泛型类
*/
public class GenericTest {
/*
* 在类方法中使用类定义的泛型
*/
public void test(List ls){
K s = ls.get(0);
System.out.println(s.toString());
}
/*
* 泛型方法
*/
public static void a(T t){
System.out.println(t.toString());
}
public static void main(String[] args) {
GenericTest.a(Integer.valueOf(1));
GenericTest.a("abc");
}
}
最后在提醒一下,擦除法并不代表编译后的字节码中就不包含我们在源代码定义的泛型类型了。而是在字节码中引入新属性Signature 和 LocalVariableTypeTable 来存储泛型。这也是为什么可以通过返回值重载,及通过反射获取到泛型的根本原因。