27

最后我尝试了一些泛型。我想出了这段代码:

public class Test {

    static <T> void f(T x) {
        x = (T) (Integer) 1234;
        System.out.println(x);
    }

    public static void main(String[] args) {
        f("a");
        f(1);
        f('a');
        f(1.5);
        f(new LinkedList<String>());
        f(new HashMap<String, String>());
    }
}

我运行了这个并得到了这个输出:

1234
1234
1234
1234
1234
1234

无一例外!这怎么可能?

4

2 回答 2

37

这是因为类型擦除(关于这个已经写了很多,只是谷歌这个词)。编译f为字节码后,该方法可能如下所示:

static void f(Object x) {
    x = (Object) (Integer) 1234;
    System.out.println(x);
}

所以System.out.println只会调用toString对象上的方法x- 在你的情况下它是Integer.toString().

于 2013-08-07T11:55:31.687 回答
4

因为类型擦除。来自Oracle 的文档

泛型被引入 Java 语言以在编译时提供更严格的类型检查并支持泛型编程。为了实现泛型,Java 编译器将类型擦除应用于:

  • 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或 Object。因此,生成的字节码只包含普通的类、接口和方法。

  • 必要时插入类型转换以保持类型安全。

  • 生成桥方法以保留扩展泛型类型中的多态性。

类型擦除确保不会为参数化类型创建新类;因此,泛型不会产生运行时开销。

于 2013-08-07T11:59:23.830 回答