zoukankan      html  css  js  c++  java
  • Java 泛型,了解这些就够用了。

    此文目录:

    1. Java泛型是什么?
    2. 通常的泛型的写法示例
    3. 类型擦除
    4. 为什么要使用Java泛型
    5. 通过示例了解PECS原则

    一、Java泛型是什么?

    • 官方定义
    泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
    这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
    • 通俗解释
    通俗的讲,泛型就是操作类型的 占位符,即:假设占位符为T,那么此次声明的数据结构操作的数据类型为T类型。

    二、通常的泛型写法示例

    • T 类型,用于泛型类或者泛型方法

      泛型类定义:

    public class ApiResult<T> {

    int resultCode; String resultMsg; T resultObject;    // 省略构造方法和 get,set方法。 }

      定义泛型方法:

      

    public class JsonUtil {
        
        public <T> T  str2Json(String jsonText,Class target){
            T result=null;
            //....parse to json 
            return result;
        }
    }

      使用:

      //泛型类使用
    ApiResult<User> result=new ApiResult<User>(); result.setResultCode(0); result.setResultMsg("success"); result.setResultObject(new User());

          ApiResult<List<User>> result2=new ApiResult<List<User>>();
          result.setResultCode(0);
          result.setResultMsg("success");
          result.setResultObject(userList);

          ApiResult<Integer> result3=new ApiResult<Integer>();
          result3.setResultCode(0);
          result3.setResultMsg("success");
          result3.setResultObject(99);

        //泛型方法使用

          String userJsonText="....省略",dogJsonText="....省略";;
              User u=JsonUtil.str2Json(jsonText,User.class);
              User u=JsonUtil.str2Json(jsonText,Dog.class);

    •  K,V类型,类似Map接口。

    定义:

    public class ResultMap<K,V> {
    
        private K key;
        private V value;
        
       //省略 set ,get  方法


    public void put(K key,V value){ this.key=key; this.value=value; } }

    使用:

            ResultMap<String,User> resultMap=new ResultMap<>();
            resultMap.put("currentUserKey", new User());
    • ?extends 类型
    <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
    • ?supper 类型
    <? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
    

      

     三、类型擦除

      先看一个例子,Operate类如下:

    public class Operate {
    
        public static void main(String[] args) {
    
            List<String> names=new ArrayList<String>();
            names.add("Jack");
            names.add("Tom");
            names.add("peter");
            for(String name:names){
                System.out.println("wellcome:"+name);
            }
        }
    
    }

    其对应的class文件反编译之后,我们使用java-gui反编译.exe  查看编译之后的代码如下

    发现没有,根本没有<String> 这一部分了。这个限制为String类型的泛型被“擦除”了。写代码的时候,泛型会做校验,类型不对应的,无法add,但是编译之后边去掉了泛型类型。

      四、什么要使用Java泛型

     在上面 第三部分介绍了“类型擦除”之后,在来说为什么要使用Java泛型就比较好说了。这里的泛型就相当于“约法三章”,先给你定好“规矩”,我这个List<String> 就是用来操作

    String类型的,你插入Person对象就不行。说白了就是为了类型安全。所以其好处有:

      类型安全:通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

    消除强制类型转换:

    //该代码不使用泛型:
    List li = new ArrayList();
    li.put(new Integer(3));
    Integer i = (Integer) li.get(0);
    
    
    //该代码使用泛型:
    List<Integer> li = new ArrayList<Integer>();
    li.put(new Integer(3));
    Integer i = li.get(0);

    了解了上面的这么多,已经足够日常使用泛型了。下面了解下PECS原则

    五、PECS原则

     先看例子:

    此处定义三个类,spiring,summer继承season
    public
    class Season { //..... } public class Spring extends Season { //...... } public class Summer extends Season { //....... }
            List<? extends Season> list1=new ArrayList<>();
            //list1.add(new Spring());//这里编译不通过,因为编译器无法确定list所持有的类型。
            List<? extends Season> list2=new ArrayList<Spring>();
    //        list2.add(new Spring());//也是无法通过编译
        //通过上文,我们知道 ?extends Season表示可以接收的类型为 Seaon 或者其子类。
    但是此处不行,因为可能传入进来的是spring,或者summer,编译器无法确定具体传递进来的是什么,
    所以无法安全的向其中添加对象,但是它可以接收子类类型 的赋值。如下:
    // List<Spring> list3=new ArrayList<Spring>(); List<? extends Season> list4=list3;//这里和上面的list2做对比,无法直接add spring类型的对象 //但是可以直接将spring类型的list赋值。 List<Season> seasons=new ArrayList<Season>(); List<? super Spring> spring=seasons; spring.add(new Spring());//ok // spring.add(new Summer());//error // spring.add(new Season());//error // spring.add(new Object());//error
            List<? super Season> sea=new ArrayList<>();
            sea.add(new Spring());//ok
            sea.add(new Summer());//ok
            sea.add(new Season());//ok
    //        sea.add(new Object());//error
            
            List<? super Spring> spring=new ArrayList<>();
            spring.add(new Spring());//ok
    //        spring.add(new Summer());//error
    //        spring.add(new Season());//error
    //        spring.add(new Object());//error

    这里 ,PECS原则 如下:

    如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)
    如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)
    如果既要存又要取,那么就不要使用任何通配符。

    Java Queue系列之PriorityQueue

    一篇图看清Java中的各种Queue

    [spring如何启动的?这里结合spring源码描述了启动过程](https://www.cnblogs.com/demingblog/p/7443714.html)
    [SpringMVC是怎么工作的,SpringMVC的工作原理](https://www.cnblogs.com/demingblog/p/9925268.html)
    [spring 异常处理。结合spring源码分析400异常处理流程及解决方法](https://www.cnblogs.com/demingblog/p/9218271.html)

    [Mybatis Mapper接口是如何找到实现类的-源码分析](https://www.cnblogs.com/demingblog/p/9544774.html)
    [使用Netty实现HTTP服务器](https://www.cnblogs.com/demingblog/p/9970772.html)
    [Netty实现心跳机制](https://www.cnblogs.com/demingblog/p/9957143.html)
    [Netty系列](https://www.cnblogs.com/demingblog/p/9912099.html)

    [Docker & k8s 系列一:快速上手docker](https://www.cnblogs.com/demingblog/p/12905545.html)
    [Docker & k8s 系列二:本机k8s环境搭建](https://www.cnblogs.com/demingblog/p/12905563.html)
    [Docker & k8s 系列三:在k8s中部署单个服务实例](https://www.cnblogs.com/demingblog/p/12905569.html)
    [Docker & Kubenetes 系列四:集群,扩容,升级,回滚](https://www.cnblogs.com/demingblog/p/12919876.html)

     逃离沙漠公众号

  • 相关阅读:
    区别@ControllerAdvice 和@RestControllerAdvice
    Cannot determine embedded database driver class for database type NONE
    使用HttpClient 发送 GET、POST、PUT、Delete请求及文件上传
    Markdown语法笔记
    Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
    Mysql 查看连接数,状态 最大并发数(赞)
    OncePerRequestFilter的作用
    java连接MySql数据库 zeroDateTimeBehavior
    Intellij IDEA 安装lombok及使用详解
    ps -ef |grep xxx 输出的具体含义
  • 原文地址:https://www.cnblogs.com/demingblog/p/5495610.html
Copyright © 2011-2022 走看看