根据我的理解,以下
java中的泛型函数:
public static <T> T f(T x) { Integer[] arr = new Integer[4]; T ret = (T) arr[2]; return ret; }
被编译成以下形式(因为它是无界的):
public static Object f(Object x) { Integer[] arr = new Integer[4]; Object ret = (Object) arr[2]; return ret; }
但是,当我运行以下语句时,编译器能够将返回值计算为整数类型.编译器如何计算出来?
Integer i = f(new Integer(4));
上述语句的功能不应该写成如下:
public static <T extends Integer> T f(T x) { Integer[] arr = new Integer[4]; T ret = (T) arr[2]; return ret; }
解决方法
泛型使用类型擦除.这基本上意味着泛型只不过是隐式的,所以当你这么做:
List<Integer> ...
与正常的列表没有什么不同,可能包含整数或任何真正的.你只是告诉Java将get()转换为整数(和其他东西).类型根本不在运行时保留(主要).
数组是不同的数组是所谓的协变.这意味着它们的类型在运行时被保留.所以你可以做:
List<Integer> list1 = new ArrayList<Integer>(); list2 = (List<String>)list1; list2.add("hello");
这是完全合法的,并将编译和运行.但:
Integer[] arr1 = new Integer[10]; String[] arr2 = (String[])arr1; // compiler error
但它也比这更微妙.
Integer[] arr1 = new Integer[10]; Object[] arr2 = (Object[])arr1; arr2[5] = "hello"; // runtime error!
关于你的功能当你写:
public static <T> T f(T x) { Integer[] arr = new Integer[4]; T ret = (T) arr[2]; return ret; }
你告诉编译器从参数中导出T作为参数类型和返回类型.所以当你传入Integer时,返回类型是Integer.你打电话时:
Integer i = f(new Integer(4));
编译器只是按照你的指示.该函数确实采用并返回一个编译形式的对象,但它只是这样做:
Integer i = (Integer)f(new Integer(4));
含蓄.
就像上面的List示例一样,没有什么阻止你有f()返回你喜欢的任何东西,而不是基于参数化类型返回的东西.