美文网首页
浅谈泛型

浅谈泛型

作者: 黄二的NPE | 来源:发表于2018-05-22 22:23 被阅读5次
    • 为什么会有泛型

    我们先从一个老生常谈的问题说起:

        List list = new ArrayList();
        list.add(1);
        list.add("2");
        for(int i = 0; i < list.size(); i ++){
            System.out.println((Integer)(list.get(i)) + 1);
        }
    

    上面的代码中,当执行到第二个循环便报错了.这是因为我们传进去的是字符串的"2",但是字符串"2"不能强制转成Integer 2, 所以报错.
    之所以会出现这种情况,是因为我们的加法运算只能是整型,但是我们的list鱼龙混杂,什么都可以加进去,那么有什么方法指定list只能添加某种类型,那肯定是有的.那就是使用泛型.我们再来看下面的代码

        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add("1");
        for(int i = 0; i < list.size(); i ++){
            System.out.println((Integer)(list.get(i)) + 1);
        }
    

    上面的代码别说运行,别说编译,就是放在idea,它也给list.add("1");报个红线处理.
    所以泛型有什么用呢?泛型能像参数一样传递类型,它能使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常.

    我们再来看一个例子
    假如没有泛型,我们想抽象可以放东西的一个盒子怎么抽象呢?我们大概会抽象盒子里面有一个object对象,用来存放东西,代码大概如下:

     public class Box{
            private int weight;
            private Object object;
    
            ...get/set...
        }
    

    这时我们有一只猫

        public class Cat{
            private String name;
            private int age;
    
           ...get/set...
        }
    

    我们想把猫放进盒子坐火车回家,等下了火车就取出来:

        public static void main(String[] args) {
            //把猫藏到盒子里面
            Box box = new Box();
            box.setObject(new Cat());
            //坐火车
            train();
            //把猫取出来
            Cat cat = (Cat)box.getObject();
    
        }
    

    有没有发现,每次我们把猫拿出去来的时候都需要先把猫强转一下,都会让我们的代码看起来很不优雅..

    • 怎么制作一个泛型

    普通泛型

    如果有了泛型,上面箱子会变成什么样子呢
    用了泛型的箱子

     public class Box<T>{
            private int weight;
            private T object;
            public Box(T object){
              this.object = object;
            }
            ...get/set...
    
          
        }
    

    在类型后面加上<T>,即完成了一个简单的泛型,这里的T表示一个Java类型,我们把一个Java类型传入T,然后Box里面所有用T修饰的类型都会变成我们传入的Java类型了.也就是说我们可以理解成传入Cat的Box就变成这样子了

     public class Box<Cat>{
            private int weight;
            private Cat object;
    
            ...get/set...
        }
    

    除了可以用T,我们还可以用其它字母,之所以用T更多的是因为前辈们的约定,类似的约定还有

    • ? 表示不确定的java类型
    • T (type) 表示具体的一个java类型
    • K V (key value) 分别代表java键值中的Key Value
    • E (element) 代表Element

    现在我们要把猫拿到箱子里过火车怎么做呢?

            //把猫藏到盒子里面
            Box<Cat> box = new Box();
            box.setObject(new Cat());
    
            //把猫取出来
            Cat cat = box.getObject();
    

    现在不用强制转换了,代码看起来也顺眼了许多

    多个泛型
        static class Hmap<K,V>{
            private K key;
            private V value;
    
            ...get/set...
          
        }
    

    这里没什么好讲的,跟一个的差不多;三个参数,四个参数也一样,无非是多几个逗号

    泛型边界
    Class BlueCat extends Cat{}
    Class RedCat extends Cat{}
    Class Cat extends Animal{}
    
    • <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
      Box<? extends Cat> box = new Box<BlueCat>(new BlueCat());
      Box<? extends Cat> 表示一个放了可能是蓝猫或者虹猫或者猫的箱子
      Cat cat = box.getObject() 因为箱子里面放的可能蓝猫,虹猫或者猫,这些都是猫,所以拿出来的肯定可以用Cat来接收
      但是box.setObject(new BlueCat())就报错了,因为这是个可能房蓝猫,虹猫或者猫的箱子,你放了个蓝猫进去,万一这是个放红猫的箱子怎么办?

    • <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
      Box<? super Cat> box = new Box<Cat>(new BlueCat());
      Box<? super Cat> box 表示这是一个放了猫的基类的箱子,猫的基类有什么呢?有动物Animal,有Object等.也就是说这是一个可能是放了Animal,Object,Cat的箱子
      Cat cat = box.getObject() 这个会报错,因为这个这是一个放了可能是Cat,Animal,Object的箱子,你拿一个Cat来接收,万一它是Animal怎么办,就接收不了了啊.
      box.setObject(new BlueCat()) 这个就可以执行,因为你BlueCat它是Cat的派生类啊..他也是Animal的孙子类啊.更不用说是Object的子类了
      box.setObject(new Dog()) 假如我们这个dog继承了Animal,这里还是报错,这里只是说可能是放了Cat,Animal,Object的箱子,万一放的是Cat那和Dog就没有什么关系了.

    泛型方法

    我们在方法的返回值类型前面加一个<T>,表示这是一个支持泛型的方法,然后我们就可以把返回值类型,参数类型等设为泛型了.其他跟泛型类差不多

        //这是我写的一个用于取数组前length个元素的方法,当list的长度小于length时,返回这个list,
        //因为假如直接list.subList(0,length),当length大于list的实际长度会报错
        public static <T> List<T> subList(List<T> list, Integer length) {
            if (list.size() <= length) {
                return list;
            }
            return list.subList(0, length);
        }
    

    相关文章

      网友评论

          本文标题:浅谈泛型

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