Java Type详解

 

带你了解Java泛型Type体系。...

今日科技快讯

5月21日,乐视网发布公告,贾跃亭申请辞去乐视网总经理职务,专任董事长一职。至于贾跃亭到底为什么辞职?尚未有定论。但有知情人士称,乐视第三大股东鑫根资本是希望乐视创始人贾跃亭辞去公司CEO的。另外,今年1月份率领融创中国出资150.41亿元成为乐视的第二大股的孙宏斌甚至直接表示:“未来,乐视主要就只有乐视网和乐视汽车,乐视汽车贾跃亭要怎么玩就怎么玩,贾跃亭的主要精力也在汽车上,乐视网还有我!”

作者简介

本篇是徐俊 的第五篇投稿了,给大家带来了Java Type的分析,希望对大家有所帮助。

徐俊 的博客地址:

http://blog.csdn.net/gdutxiaoxu

前言

错误可分为两种:编译时错误与运行时错误。编译时错误在编译时可以发现并排除,而运行时错误具有很大的不确定性,在程序运行时才能发现,造成的后果可能是灾难性的。

泛型的引入使得一部分错误可以提前到编译时期发现,极大地增强了代码的健壮性。但是我们知道 Java 泛型在运行的时候是会进行泛型擦除的,那我们要怎样得到在编译时期泛型的信息呢?Java 为我们提供了 Type 接口,使用它,我们可以得到这些信息。

不知道什么是泛型擦除的同学可以看一下.

类型擦除是指泛型在运行的时候会去除泛型的类型信息。java 中,泛型主要是在编译层次来实现的,在生成的字节码即 class 文件是不包括泛型的 类型信息的。 即 List, List ,List 虽然在编译时候是不同的,但是在编译完成后,在 class文件 中都只会把他们当作 List 来对待。

Type接口简介

类 UML 图如下
简单来说:Type 是所有类型的父接口, 如原始类型(raw types 对应 Class)、 参数化类型(parameterized types 对应 ParameterizedType)、 数组类型(array types 对应 GenericArrayType)、 类型变量(type variables 对应 TypeVariable )和基本(原生)类型(primitive types 对应 Class),。

子接口有 ParameterizedType, TypeVariable, GenericArrayType, WildcardType, 实现类有Class。

ParameterizedType(参数化类型)

官方文档的说明是这样的

ParameterizedType represents a parameterized type such as Collection

需要注意的是,并不只是 Collection 才是 parameterized,任何类似于 ClassName 这样的类型都是 ParameterizedType ,比如下面的这些都是 parameterizedType.

Map map;
Set set1;
Class clz;
Holder holder;
List list;
static class Holder{}而类似于这样的 ClassName 不是 ParameterizedType.

Set set;
List aList;

ParameterizedType 的几个主要方法

  • Type[] getActualTypeArguments();
  • Type getRawType();
  • Type getOwnerType();
Type[] getActualTypeArguments() 返回这个 Type 类型的参数的实际类型数组。 如 Map map 这个 ParameterizedType 返回的是 String 类,Person 类的全限定类名的 Type Array。

Type getRawType() 返回的是当前这个 ParameterizedType 的类型。 如 Map map 这个 ParameterizedType 返回的是 Map 类的全限定类名的 Type Array。

Type getOwnerType()

Returns a {@code Type} object representing the type that this type is a member of.

这个比较少用到。返回的是这个 ParameterizedType 所在的类的 Type (注意当前的 ParameterizedType 必须属于所在类的 member)。解释起来有点别扭,还是直接用代码说明吧。 比如 Map map 这个 ParameterizedType 的 getOwnerType() 为 null,而 Map.Entryentry 的 getOwnerType() 为 Map 所属于的 Type。

说了这么多,下面我们一起来看一下例子,加深印象。
TypeVariable变量

比如 public class TypeVariableBean,主要方法

  • Type[] getBounds() 得到上边界的 Type数组,如 K 的上边界数组是 InputStream 和 Serializable。 V 没有指定的话,上边界是 Object
  • D getGenericDeclaration() 返回的是声明这个 Type 所在的类 的 Type
  • String getName() 返回的是这个 type variable 的名称
执行上述代码,将可以看到如下的效果:

K
class com.xujun.gennericity.beans.TypeVariableBean

GenericArrayType

represents an array type whose component type is either a parameterized type or a type variable.

简单来说就是:范型数组,组成数组的元素中有范型则实现了该接口; 它的组成元素是 ParameterizedType 或 TypeVariable 类型
下面我们一起来看一下例子:


输出结果:
WildcardType通配符的类型

{@code ?}, {@code ? extends Number}, or {@code ? super Integer} 这些类型 都属于 WildcardType

extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null。

几个主要方法介绍

  • Type[] getLowerBounds() 得到上边界 Type 的数组
  • Type[] getUpperBounds() 得到下边界 Type 的数组
下面一起来看一下例子。


Java Type总结

Type及其子接口的来历

  • 泛型出现之前的类型
没有泛型的时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型。

  • 泛型出现之后的类型
泛型出现之后,扩充了数据类型。从只有原始类型扩充了参数化类型、类型变量类型、限定符类型 、泛型数组类型。

为什么会产生泛型擦除的原因

我们知道在 jdk 1.5 以前的时候,是没有 泛型的。在 jdk 1.5 的时候,才引入了泛型。如果真的在动态运行的时候加入泛型,涉及到 JVM 命令的修改,这无疑是非常致命的。因此折中采取了这样的策略,在编译的时候进行检查,在运行的时候进行擦除,也是我们说的泛型擦除。 同时这也说明一点,在设计框架的时候,框架的健壮性和灵活性非常重要。

为什么要学习 Type

我们知道现在的框架都会使用泛型,掌握 Type 有利于我们读懂它们的源码,或者自己动手打造框架。如 Android 的常用开源框架 Gson ,Retrofit等。

Demo下载地址:

http://download.csdn.net/detail/gdutxiaoxu/9800329

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。
如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:


    关注 郭霖


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册

泛型 相关文章