美文网首页
Java 泛型

Java 泛型

作者: BitterOutsider | 来源:发表于2020-12-07 10:48 被阅读0次

    为什么需要泛型

    假设我们在2000年,那时候是没有泛型的,如何实现类型安全呢?答案是没办法,我们可以在一个 List中随心所欲的添加不同类型的对象。如果一定要实现一个只能放String类型的List怎么办?只能用如下的代码。如果还需要一个只能Integer类型的呢?我们需要复制好多次,才能实现全部的需求。

    class StringListDecorator {
        List list = new ArrayList();
    
        void add(String s) {
            list.add(s);
        }
    
        int size() {
            return list.size();
        }
    
        String get(int i) {
            return (String) list.get(i);
        }
    }
    

    有了泛型后,一切都简单了。泛型的好处:1.安全 2.方便。

    List<String> list = new ArrayList<>();
    

    泛型的擦除

    • 引入泛型后,为了保证向后兼容性,有两条路可以选择:1.擦除(Java的选择) 2.搞一套全新的API(C#的选择)。为了验证Java是类型擦除的,我们写了如下的代码:
    public class Main {
        public static void main(String[] args) {
            String[] strings = new String[0];
            new ArrayList();
        }
    }
    

    使用ASMPlugin插件去看字节码,我们可以清楚的看到,L0:数组确实是有类型String的。而L1:ArrayList的类型却被擦除了。那为什么我们往带String泛型的List中插入Integer会报错呢?这只是编译器报错,Java的泛型是假泛型,是编译期的泛型,泛型信息在运⾏期完全不保留。所以说我们只要绕过编译器的检查,一切泛型都没有了,运行时是不会去检查的。

     public class com/github/lazyben/Main {
      // .......
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 8 L0
        ICONST_0
        ANEWARRAY java/lang/String
        ASTORE 1
       L1
        LINENUMBER 9 L1
        NEW java/util/ArrayList
        DUP
        INVOKESPECIAL java/util/ArrayList.<init> ()V
        ASTORE 2
      // .......
    }     
    
    • 我们知道StringObject的子类, String[]Object[]的子类。但List<String>并不是List<Object>的⼦类型。

    泛型的绑定

    看一个简单的例子,我们可以做一个泛型的绑定以简化代码。

    public class Main {
        public int max(int a, int b) {
            return a > b ? a : b;
        }
    
        public double max(double a, double b) {
            return a > b ? a : b;
        }
    
        public long max(long a, long b) {
            return a > b ? a : b;
        }
    }
    

    声明<T extends Comparable>表示T一定继承了Comparable接口,JVM会根据你传进来的参数做泛型的绑定。extends要求泛型是某种类型及其⼦类型

    public <T extends Comparable<T>> T max(T a, T b) {
        return a.compareTo(b) > 0 ? a : b;
    }
    

    再来看一个关于super的例子,以Collections.sort为例:

    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
    }
    

    sort的第二个参数接受一个Comparator,他的泛型必须是T及其父类,由此Comparator<Cat>Comparator<Animal>都是可以的。 super要求泛型是某种类型及其⽗类型

    public class Main {
        public static void main(String[] args) {
            final ArrayList<Cat> cats = new ArrayList<>();
            Collections.sort(cats, new CatComparator());
            Collections.sort(cats, new AnimalComparator());
        }
    
        static class CatComparator implements Comparator<Cat> {
            @Override
            public int compare(Cat o1, Cat o2) {
                return 0;
            }
        }
    
        static class AnimalComparator implements Comparator<Animal> {
            @Override
            public int compare(Animal o1, Animal o2) {
                return 0;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Java 泛型

          本文链接:https://www.haomeiwen.com/subject/bfeawktx.html