美文网首页
浅谈泛型

浅谈泛型

作者: 黄二的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);
    }

相关文章

  • 浅谈泛型

    为什么会有泛型 我们先从一个老生常谈的问题说起: 上面的代码中,当执行到第二个循环便报错了.这是因为我们传进去的是...

  • 浅谈Java泛型

    使用泛型的目的 当我们第一次接触泛型时,第一个问题肯定会是,为什么要使用泛型?最直接的答案是为了避免转型,使得编译...

  • 泛型 & 注解 & Log4J日志组件

    掌握的知识 : 基本用法、泛型擦除、泛型类/泛型方法/泛型接口、泛型关键字、反射泛型(案例) 泛型 概述 : 泛型...

  • 【泛型】通配符与嵌套

    上一篇 【泛型】泛型的作用与定义 1 泛型分类 泛型可以分成泛型类、泛型方法和泛型接口 1.1 泛型类 一个泛型类...

  • 浅谈java的泛型

    什么是泛型 这个概念很抽象,举个例子List list = new ArrayList<>(); V...

  • 泛型的使用

    泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法 泛型类 泛型接口 泛型通配符 泛型方法 静态方法与...

  • Java 泛型

    泛型类 例如 泛型接口 例如 泛型通配符 泛型方法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型上下边...

  • 探秘 Java 中的泛型(Generic)

    本文包括:JDK5之前集合对象使用问题泛型的出现泛型应用泛型典型应用自定义泛型——泛型方法自定义泛型——泛型类泛型...

  • Web笔记-基础加强

    泛型高级应用 自定义泛型方法 自定义泛型类 泛型通配符? 泛型的上下限 泛型的定义者和泛型的使用者 泛型的定义者:...

  • 重走安卓进阶路——泛型

    ps.原来的标题 为什么我们需要泛型? 泛型类、泛型接口和泛型方法(泛型类和泛型接口的定义与泛型方法辨析); 如何...

网友评论

      本文标题:浅谈泛型

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