• Java泛型漫谈


    介绍java泛型的定义以及实际的具体使用方法。

    什么是泛型?

    泛型是JDK5引入的新特性,本质是参数化类型。在定义的时候无需知道参数的具体类型,即将参数类型推迟到使用时决定。

    这种参数类型可以体现在类,接口,方法中,我们可以称呼为泛型类,泛型接口,泛型方法。

    为什么使用泛型?

    • 保证类型安全

      举个例子,我们都知道List只能存放同种类型的参数,在没有泛型之前是无法得知不同类型的参数存放到同一个list中是否报错

      /**
      * 泛型出现之前
      */
      List list = new ArrayList();
      // 本意是想在该list中存放字符串类型的参数
      list.add("测试");
      // 由于没有泛型指定参数类型,同样编译通过
      list.add(1);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      /**
      * 泛型出现之后
      */
      List<String> list = new ArrayList<>();
      // 本意是想在该list中存放字符串类型的参数
      list.add("测试");
      // 编译失败
      list.add(1);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 消除强制转换

      如果没有泛型,无法得知List中存放的具体是某种参数类型,所以无法避免强制转换。

      /**
      * 泛型出现之前
      */
      List list = new ArrayList();
      // 本意是想在该list中存放字符串类型的参数
      list.add("测试");
      // 必须通过强制转换
      String a = (String) list.get(0);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      /**
      * 泛型出现之后
      */
      List<String> list = new ArrayList<>();
      // 本意是想在该list中存放字符串类型的参数
      list.add("测试");
      // 无需强制转换
      String a = list.get(0);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 避免重复拆装箱操作

    • 提高代码可用性

    泛型使用

    泛型命名规范,一般都是使用单个大写字母来指定,例如T或者R等等。

    泛型类

    泛型定义在类上,定义格式如下:

    public class ClassName <T> {
        
    }
    
    • 1
    • 2
    • 3

    我们模拟一个场景,小朋友写数字,有些小朋友写的int类型的阿拉伯数字,有些小朋友写的是字符串的中文数字,于是我们定义一个Child类,并指定一个泛型T来接收小朋友报的数:

    public class Child <T> {
        private T value;
        
        // 定义一个泛型T构造函数
        public Child(T value) {
            this.value = value;
        }
     
        public T getValue() {
            return value;
        }
     
        public void setValue(T value) {
            this.value = value;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    public static void main(String[] args){
        Child<String> childOne = new Child<>("一");
        // 1号小朋友写的是字符串类型的中文数字一
        System.out.println(childOne.getValue());
        Child<Integer> childTwo = new Child<>(1);
        // 2号小朋友写的是字符串的int类型的阿拉伯数字1
        System.out.println(childTwo.getValue());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    泛型接口

    泛型定义在接口中,例如:

    public interface Test<T>{
        void test(T value);
    }
    
    • 1
    • 2
    • 3

    泛型方法

    泛型定义在方法上,定义格式如下:

    public <T> T test(T t){
        return t;
    }
    
    • 1
    • 2
    • 3

    举例,接收同种类型的两个参数,输出不为null的结果:

    public static <T> T firstNonNull(@CheckForNull T first, T second) {
        if (first != null) {
            return first;
        }
        if (second != null) {
            return second;
        }
        throw new NullPointerException("Both parameters are null");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    该例子取自Google的guava源码。

    扩展

    对于泛型经常使用的还有泛型通配符,有以下三种使用方式:

    1. 无边界的泛型
    2. 上边界泛型
    3. 下边界泛型
    public class MyClass <?>{
    }
    
    public class MyClass <T extends XxxClass>{
    }
    
    public class MyClass <T super XxxClass>{
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    源码中的泛型通常使用E,K,V等,实际上他们都是有实际含义的:

    E:Element (在集合中使用,因为集合中存放的是元素)
    T:Type(Java 类)
    K:Key(键)
    V:Value(值)
    N:Number(数值类型)
    ?:表示不确定的java类型

    那么我们再思考一个问题,泛型具体是如何实现的呢。

    我们都知道Object是所有类的父类,那么实际上泛型就是当你定义的时候用Object来接收,然后通过尖括号里定义的泛型类型来进行类型限定,例如String或者Integer等

    除非是使用了泛型通配符,例如,那么会使用Aclass来接收。

    参考资料:

  • 相关阅读:
    vue快速学习02、基础用法
    开放内容处理框架(OCPF),轻松玩转各类数据处理
    Java代码审计安全篇-XXE(XML外部实体注入)漏洞
    Anaconda安装pytorch环境备份(更新中)
    Hadoop入门(二):手把手带你从零基础到完整安装配置
    JS原生-弹框+阿里巴巴矢量图
    山东大学单片机原理与应用实验 3.4 矩阵键盘扫描实验
    基于STM32的物联网体感控制机械臂
    ApplicationContext种类
    BUG系列路径规划算法原理介绍(六)——BugFlood算法
  • 原文地址:https://blog.csdn.net/imVainiycos/article/details/127548712