Java泛型擦除与重载
(一)泛型与类型擦除
Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型,即对运行期的java来说ArrayList<int>与ArrayList<String>
就是同一个类。
泛型擦除前的例子:
public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("hello","你好"); map.put("how are you?", "你好吗?"); System.out.println(map.get("hello")); System.out.println(map.get("how are you?")); }
把上面这段代码编译成class文件,然后再用字节码反编译工具进行反编译后,将会发现泛型都不见了,泛型类型都变回了原生类型。
泛型擦除后的代码:
public static void main(String[] args) { Map map = new HashMap(); map.put("hello","你好"); map.put("how are you?", "你好吗?"); System.out.println(map.get("hello")); System.out.println(map.get("how are you?")); }
(二)当泛型遇见重载
泛型遇见重载1:
public class GenericTypes{ public static void method(List<String> list) { System.out.println("invoke method(List<String> list)"); } public static void method(List<Integer> list) { System.out.println("invoke method(List<Integer> list)"); } }
上面这段代码是不能被编译的,因为参数List<Integer>和List<String>
编译之后都被擦除了,变成了一样的原生类型List<E>
。
那给两个方法添加不同的返回值呢?能否通过编译?
泛型遇见重载2:
public class GenericTypes{ public static String method(List<String> list) { System.out.println("invoke method(List<String> list)"); return ""; } public static int method(List<Integer> list) { System.out.println("invoke method(List<Integer> list)"); return 1; }
经常遇到的面试题:方法重载与返回值类型有关吗?无关。
方法重载要求方法具备不同的特征签名,java代码中的方法特征签名只包括方法名称、参数顺序及参数类型,不包括返回值,所以返回值不参与重载选择。
所以上述代码通常不能通过编译,书中作者提到必须使用的Sun JDK1.6的javac才能编译成功,其他版本或者ECJ编译器都可能拒绝编译。