加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Java 泛型,了解这些就够用了。

发布时间:2021-05-21 07:23:19 所属栏目:大数据 来源: https://www.jb51.cc
导读:? 此文目录: Java泛型是什么? 通常的泛型的写法示例 类型擦除 为什么要使用Java泛型 通过示例了解PECS原则 ? 一、Java泛型是什么? 官方定义 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 这种参数类

?

此文目录:

  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方法。 }

  定义泛型方法:

  

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接口。

定义:

class ResultMap<K,V> {

    private K key;
     V value;
    
   //省略 set,get  方法


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类如下:

 Operate {

    static  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());
Integer i = li.get(0);

?

?

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

五、PECS原则

?

 先看例子:

此处定义三个类,spiring,summer继承season
public
Season { ..... } class Spring extends...... class Summer 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>super Spring> spring=seasons; spring.add(new Spring());ok spring.add(new Summer());error spring.add(new Season()); spring.add(new Object());error

?

        List<? super Season> sea=();
        sea.add(ok
        sea.add(new Summer());new Season());        sea.add(new Object());error
        
        List<? ();
        spring.add(error

这里 ,PECS原则 如下:

如果要从集合中读取类型T的数据,并且不能写入,可以使用 ?  通配符;(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)

?

逃离沙漠公众号

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读