java 泛型

java1.5 引入了泛型

没有泛型的年代

// 没有泛型时,如下这样写是不会报错的,现在这样写也不会报错,但是编译器会警告
public static void main(String[] args) {
    List list = new ArrayList();
    list.add(new Object());
    list.add(1);
    list.add("foolish");
}

那没有泛型时怎么保证类型安全呢,可以如下这样自己封装一个(装饰器)只能加入字符串 的 List,但是我们不能无休止的自己封装仅限某个类的 List。

public class Main {
    public static void main(String[] args) {
        ListString list = new ListString();
        list.add("泛型");

    }

    static class ListString {
        List list = new ArrayList();

        public void add(String s) {
            list.add(s);
        }

        public int size() {
            return list.size();
        }

        public String get(int i) {
            return (String) list.get(i);
        }
    }
    static class ListInt {
        List list = new ArrayList();

        public void add(int s) {
            list.add(s);
        }

        public int size() {
            return list.size();
        }

        public int get(int i) {
            return (int) list.get(i);
        }
    }
}

有了泛型就简单多了

为什么说 java 泛型是“假泛型”

java 从没有泛型的时代走到有泛型的时代,那 java1.5 之前的代码怎么做兼容? 有两个方案:

  1. 擦除【java 的选择】

  2. 提供一套全新 API【c#的选择】

什么是擦除,看如下 Main.java 文件

我们对 Main.java 文件使用: javac -encodeing utf-8 Main.java 进行编译之后,打开编译后的 Main.class 的文件:

对应的字节码文件为:

我们发现 ArrayList<String> stringArrayList = new ArrayList<>();的本质还 是ArrayList var2 = new ArrayList()/NEW java/util/ArrayList,所传递的泛型类被 擦除了。因为 jvm 最终运行的是生成的.class 文件,所以说 java 的泛型是“假泛型”,是 编译期泛型,只在编译期进行泛型类型检查。

擦除带来的问题

你会发现如下代码编译器会发出 Error 警告: 'foo(List)' clashes with 'foo(List)'; both methods have same erasure 这就是擦除带来的问题,两个 foo 方法并不会重载,而是会报 same erasure 错误。

让我们再看一个绕过编译器检查的例子:

泛型的绑定

Last updated

Was this helpful?