此文目录:

  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)

Java 泛型,了解这些就够用了。的更多相关文章

  1. java泛型应用实例 - 自定义泛型类,方法

    近 短时间需要使用泛型,就研究了下,发现网上的问关于泛型的文章都是讲原理的, 很少有提到那里用泛型比较合适, 本文就泛型类和泛型方法的使用给出两 个典型应用场景. 例如一个toString的泛型方法, ...

  2. Java 泛型(Generics) 综述

    一. 引子 一般的类和方法.仅仅能使用详细类型:要么是基本类型.要么是自己定义类型.假设要编写能够应用于多种类型的代码,这样的刻板的限制对代码的束缚就会非常大. 多态算是一种泛化机制,但对代码的约束还 ...

  3. Java泛型解析(01):认识泛型

    Java泛型解析(01):认识泛型 What      Java从1.0版本号到如今的8.中间Java5中发生了一个非常重要的变化,那就是泛型机制的引入.Java5引入了泛型,主要还是为了满足在199 ...

  4. Java泛型的历史

    为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...

  5. 浅析Java 泛型

    泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...

  6. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

  7. java泛型基础

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法.  Ja ...

  8. 使用java泛型设计通用方法

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...

  9. 关于Java泛型的使用

    在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Wind ...

随机推荐

  1. 起因:dell超级密码算号器 1F66

    班里有几个比较调皮的同学~(显然不包括我[开玩笑的]) 当初班长设置了密码,结果那几个玩拳皇的想玩,就找我删除了密码~ 最后有个大神就过来设置了BIOS.有种终于出动了的样子.有种我看你怎么办的样子. ...

  2. zjuoj 3608 Signal Detection

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3608 Signal Detection Time Limit: 2 Sec ...

  3. C#,JS获取mac地址

    js: function MacInfo() { var locator = new ActiveXObject("WbemScripting.SWbemLocator"); va ...

  4. 运行TLD

    TLD(跟踪学习检测)是英国萨里大学的捷克学生Zdenek Kalal在其2010的一篇论文中提出的实时性较好的单目标长时间跟踪算法.其主页上有相关的文章下载,源码是从这里下载的,还可以找到安装步骤, ...

  5. Excel 统计在某个区间内数值的个数

    =COUNTIF(A1:A50,"<=1.0E-5")-COUNTIF(A1:A50,"<60")

  6. Objective-C语言多态性

    动态类型和动态绑定,id可以表示任何指针类型,定义id变量不加* 多态性是指在父类中定义的成员变量和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为.这使得同一个变量和方法在父类及其各个子 ...

  7. stack overflow--技术问答网站

    转自:http://baike.baidu.com/link?url=eMR6Pwdk9IkauI5B3nZb2Yo3VUAcK6vQfrMpcSMPWqgH0ngqFkup3Gdr3t_s_yZe_ ...

  8. NET中的类型和装箱/拆箱原理

    谈到装箱拆箱,DebugLZQ相信给位园子里的博友一定可以娓娓道来,大概的意思就是值类型和引用类型的相互转换呗---值类型到引用类型叫装箱,反之则叫拆箱.这当然没有问题,可是你只知道这么多,那么Deb ...

  9. 给NIOS II CPU增加看门狗定时器并使用

    给NIOS II CPU增加看门狗定时器并使用   配置看门狗定时器: 设置计时溢出时间为1秒 计数器位宽为32位 勾选No Start/Stop control bits 勾选Fixed perio ...

  10. Codeforces 749C:Voting(暴力模拟)

    http://codeforces.com/problemset/problem/749/C 题意:有n个人投票,分为 D 和 R 两派,从1~n的顺序投票,轮到某人投票的时候,他可以将对方的一个人K ...