image.png

泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。利用好泛型,在系统架构中是一把利器。

泛型类

先看一个例子,restful架构中,需要定义api接口返回结构,定义如下:

package com.company.project.core;

import com.alibaba.fastjson.JSON;

/**

* 统一API响应结果封装

*/

public class Result {

private int code;

private String message;

private Object data;

public Result setCode(ResultCode resultCode) {

this.code = resultCode.code;

return this;

}

public int getCode() {

return code;

}

public Result setCode(int code) {

this.code = code;

return this;

}

public String getMessage() {

return message;

}

public Result setMessage(String message) {

this.message = message;

return this;

}

public Object getData() {

return data;

}

public Result setData(Object data) {

this.data = data;

return this;

}

@Override

public String toString() {

return JSON.toJSONString(this);

}

}

这是最常见的做法,这样做的一个坏处是消息体data的元素我们不知道是什么类型,需要强制转换,另外如果用swagger的话,在线文档解析不出data具体的字段内容,api接口使用者不知道应该怎么解决这个data对象,使用泛型可以很好的解决这个问题。

package cn.watchvip.mall.common.core;

import com.alibaba.fastjson.JSON;

/**

* 统一API响应结果封装

*/

public class Result {

private int code;

private String msg;

private T data;

public Result setCode(ResultCode resultCode) {

this.code = resultCode.code;

return this;

}

public int getCode() {

return code;

}

public Result setCode(int code) {

this.code = code;

return this;

}

public String getMsg() {

return msg;

}

public Result setMsg(String msg) {

this.msg = msg;

return this;

}

public T getData() {

return data;

}

public Result setData(T data) {

this.data = data;

return this;

}

@Override

public String toString() {

return JSON.toJSONString(this);

}

}

泛型方法

泛型方法只需要在方法签名的返回值前加一个类似形式即可,我们拿jdk中Collections工具类中的方法加以说明

获取一个空集合:

public static final List emptyList() {

return (List) EMPTY_LIST;

}

获取一个空Map

public static final Map emptyMap() {

return (Map) EMPTY_MAP;

}

这样就可以获取任何类型的空集合了,如下:

List emptyList = Collections.emptyList();

Map emptyMap = Collections.emptyMap();

边界符 >

掌握了泛型类与泛型方法基本能满足大部分开发中的需要了,但还远不够,考虑这样一个需求,查找一个泛型数组中大于某个特定元素的个数,我们可以通过泛型方法这样实现:

public static int countGreaterThan(T[] anArray, T elem) {

int count = 0;

for (T e : anArray)

if (e > elem) // compiler error

++count;

return count;

}

但是这样很明显是错误的,因为除了short, int, double, long, float, byte, char等原始类型,其他的类并不一定能使用操作符>,所以编译器报错,那怎么解决这个问题呢?答案是使用边界符。

public interface Comparable {

public int compareTo(T o);

}

做一个类似于下面这样的声明,这样就等于告诉编译器类型参数T代表的都是实现了Comparable接口的类,这样等于告诉编译器它们都至少实现了compareTo方法。

public static > int countGreaterThan(T[] anArray, T elem) {

int count = 0;

for (T e : anArray)

if (e.compareTo(elem) > 0)

++count;

return count;

}

通配符 extends T>

不能往里存,只能往外取

在讨论通配符之前,我们设想一下如果我们考虑实现一个可以对int,flow,bouble类型都可以进行做加法的方法,我想90%的人都会写出以下方法

public static void add(Collection c){

}

public static void main(String[] args) {

List integers = Arrays.asList(1, 2, 3);

List doubles = Arrays.asList(1.1, 2.1);

add(integers);//不允许

add(doubles);//不允许

}

众所周知,java是可以向上转型的,这也是我们面向接口编程的基础,如下:

List list = new ArrayList();

list = new LinkedList<>();

但泛型却是不支持向上转的,

List list = new ArrayList(); //编译不通过

虽然Integer是Number的子类,但在泛型中,两个是完全没有关系的。

add方法中的参数Collection按我们熟悉的继承,不是可以传入Collection,Collection么?答案是否定的,虽然,Integer和Double都是Number的子类,但在泛型中,Collection与Collection,Collection没有任何关系。那么如果我们确实需要建立这种 “向上转型” 的关系怎么办呢?这就需要通配符来发挥作用了。即告诉编译器,使用者可以传入Collection,也可以传入Collection,利用 extends Number> 形式的通配符,就可以实现泛型的向上转型:

public static void add(Collection extends Number> c){

}

public static void main(String[] args) {

List integers = Arrays.asList(1, 2, 3);

List doubles = Arrays.asList(1.1, 2.1);

add(integers);

add(doubles);

}

通配符

只能往里存,不能往外取

其它

List,List,List>的区别

List>,也就是没有任何限定。不做任何限制,跟不用类型参数的 List 有什么区别呢?

List> list 表示 list 是持有某种特定类型的 List,但是不知道具体是哪种类型。那么我们可以向其中添加对象吗?当然不可以,因为并不知道实际是哪种类型,所以不能添加任何类型,这是不安全的。而单独的 List list ,也就是没有传入泛型参数,表示这个 list 持有的元素的类型是 Object,因此可以添加任何类型的对象,只不过编译器会有警告信息。

java中什么时候不能用泛型_java中泛型的正确使用姿势相关推荐

  1. java中什么泛型_java中的泛型(一)

    在java中我们定义接口其实定义的是这个类的功能,在很多时候我们并不关心这个类的类型而是这个类的能力.泛型的出现让我们的代码和代码所能操作的类型不在绑定在一起,不仅可以复用代码降低耦合还可以提高代码的 ...

  2. java中什么泛型_Java中的泛型

    1.为什么要使用泛型? (1)适用于多种数据类型执行相同的代码,利于封装(如,封装Base类.统一的适用于recycleview的adapter等) (2)泛型中的类型在使用的时候,直接指定即可,不需 ...

  3. java 类 方法 带泛型_java中的泛型类和泛型方法

    1.泛型是什么? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类. 可以在集合框架(Collection fram ...

  4. java基本数据类型泛型_Java中的泛型

    泛型规范在JDK1.5版本中被添加,使用泛型机制编写的代码比起随意使用Object变量然后再进行强制类型转换的代码具有更高的安全性和可读性,同时也更为简洁.泛型对于集合类尤其有用,例如 ArrayLi ...

  5. java中char是几个字节_Java中char占用几个字节

    在讨论这个问题之前,我们需要先区分unicode和UTF. unicode :统一的字符编号,仅仅提供字符与编号间映射.符号数量在不断增加,已超百万.详细:[https://zh.wikipedia. ...

  6. Java传统的io和nio区别_Java中IO和NIO的本质和区别

    简介 终于要写到java中最最让人激动的部分了IO和NIO.IO的全称是input output,是java程序跟外部世界交流的桥梁,IO指的是java.io包中的所有类,他们是从java1.0开始就 ...

  7. java语言中的数据是如何定义_java中的数据类型

    java中的数据类型 java语言的数据类型包括两种,基本数据类型和引用数据类型. 定义 基本数据类型:变量名指向具体的数值. 引用数据类型:变量名指向存数据对象的内存地址,即变量名指向hash值. ...

  8. java 继承 实现 会重写 方法吗_java 中继承,组合,重载,重写的实现原理 (转)...

    我们知道,继承,组合,重载,重写是java语言的面向对象实现的基本特征. 那么在java内部,究竟是如何实现这些面对对象的基本特征的呢? 继承和组合是面向对象中代码复用的主要实现方式,他们可以达到类似 ...

  9. java如果把字符串转成对象_Java中的重复对象:不仅仅是字符串

    当Java应用程序消耗大量内存时,它本身就会出现问题,并可能导致GC压力增加和GC暂停时间过长.在我之前的一篇文章中,我讨论了Java中常见的内存浪费源:重复字符串.两个 java.lang.Stri ...

最新文章

  1. MassTransit_契约的创建
  2. 联想激发青年公益创业彰显“责任”意识
  3. SQL_Server2008数据连接池
  4. 直方图和直条图_绘图专题 | 条形图/直方图傻傻分不清楚
  5. 服务器应用程序不可用您试图在此 Web 服务器上访问的 Web 应用程序当前不可用。请点击 Web 浏览器中的“刷...
  6. 音视频技术开发周刊 | 201
  7. 全国计算机等级考试题库二级C操作题100套(第15套)
  8. POJ 1088-滑雪
  9. java企业级开发SSM
  10. bll调用mysql存储过程_SQL Server的存储过程或自定义函数调用Com组件
  11. Microsoft Edge 浏览器如何打开Axure RP文件
  12. php自动盖章,印章自动生成器?
  13. 淘宝平台搜索规则变化,怎么提升搜算转换率?
  14. 看华为生态大学 如何玩转人才生态?
  15. java登陆界面图片_java登陆界面如何插入背景图片
  16. PostGIS教程一:PostGIS介绍
  17. 分布式事务之 LCN 框架实现方案的原理、配置与使用
  18. NOIP2003 侦探推理
  19. Maven 入门教程
  20. r ridge回归_R语言逻辑回归和泊松回归模型对发生交通事故概率建模

热门文章

  1. RFID技术助力提升衣物租借效率
  2. Visual Studio® 2010 Web Deployment Projects站点编译生成bin同时发表插件
  3. 欧洲、加拿大、澳大利亚新增2.1万个点可购买比特币现金
  4. 比特币耶稣Roger Ver:BCH是世界上最创新、最实用的加密货币之一
  5. 解决linux系统CentOS下调整home和根分区大小
  6. S2系统相关-uptime命令总结(S代表系统相关)
  7. pro git读书笔记
  8. iOS开发-UITextField手机号和邮箱验证
  9. Maven3路程(三)用Maven创建第一个web项目(1)
  10. 利用套接字实现进程通信一例