转载请注明出处:https://my.oschina.net/u/874727/blog/747427

Q:1025250620

在很多Java的开源项目中都用到Java的泛型。比如Gson,就可以通过TypeToken里的泛型参数来指定生成的类型。鉴于网上关于泛型的文章并不多,为了非墨后面项目研究的需要,非墨开始研究这部分的API。首先我们先来看一下在Java语言中泛型的例子:

public class MyTest {

T1 member;

public void method(T m) {}

}

上述代码中的标志:T1,T2,T都是泛型类型。Java的泛型检查发生在编译期,但是会在编译后的JVM字节码中增加类型判断的语句。为了方便大家理解这句话我们用一段代码测试一下:

List list = new ArrayList<>();

try {

Method m = list.getClass().getDeclaredMethod("add", new Class[]{Object.class});

m.invoke(list, 1);

m.invoke(list, 2);

} catch (Exception e) {

System.out.println("error");

}

在上述代码中,虽然List变量指定了内部元素的类型String,但是在JVM运行期间list对象的add方法调用的还是add(Ljava/lang/Object)签名的方法。所以此段代码执行以后,控制台不会有任何的输出。基于此段代码的基础上,我们增加另一段验证代码:

for (Object o:list) {

System.out.println(">>"+o);

}//println >>1 >>2

//will error

System.out.println("--->"+list.get(0));

我们打印list中的子元素,如果子元素类型是Object类型的话代码正常运行。但是如果我们直接通过list.get的方式来获取元素的时候程序就会抛出一个Class Cast异常。这是为什么呢?我们来看一下编译后的JVM字节码:

95:iconst_0

96:invokeinterface#56, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;

101:checkcast#62; //class java/lang/String

我们看到,Java编译器在执行段后插入了"checkcast"指令。也就是说Java的泛型只不过是在执行期间增加了一些类型的检查语句。但是,尽管泛型发生在编译器,但是java还是把类型记录在类型对象中。这就是我们今天讨论的主角Type对象。我们看一下Type类型的继承树:

可以看出,Type类型有四个直接接口子类,一个实现类。此外还有另外一个接口GenericDeclaration。这个接口注明哪个类可以声明泛型。按照我们通过第一代码块可以知道,在Java语言中,可以声明泛型的是类,方法。为什么没有成员变量呢?我们在第一个代码块中的"T1 member"不也是泛型声明么?

或许这里我们应该换一个说法,对于member变量来说,它只是使用了泛型而并不是声明了泛型,声明T1泛型的是MyTest类。我们把构造器也看成方法的一部分,方法作为可执行提,在方法和构造器类的基础上JAVA又做了一层抽象--Executable类。

Type类型的四个直接子类注释里已经给出了解释。由于这些东西在javadoc中也说的并不详细,也很难用辞藻把他描述的非常清楚。为了让大家理解,非墨用一些简单的代码来让大家更加直观的理解他们是个什么东东。我们先将可能涉及到的泛型类型和声明方式都写到一个类中:

public static class TypeClazz {

public T2 member;

public T1 member2;

public Collection extends Number> collection;

public Collection collection2;

public T2[] array;

public void method(T p1,T2 p2) {}

}

这个类基本涵盖了所有的泛型情况。我们还需要增加一些方法来打印我们所关心的信息:

public static Type printlnFieldType(String name) {

System.out.println("name:"+name);

Class clazzType = TypeClazz.class;

Type type = null;

try {

Field field = clazzType.getDeclaredField(name);

type = field.getGenericType();

printlnType(field.getGenericType());

} catch (Exception e) {}

if (type instanceof ParameterizedType) {

ParameterizedType ptype = (ParameterizedType)type;

Type[] types = ptype.getActualTypeArguments();

for (Type t:types) {

System.out.print(">>");

printlnType(t);

}

}

return type;

}

public static void printlnMethodReturnType(String name) {

System.out.println("name:"+name);

Class clazzType = TypeClazz.class;

try {

Method[] ms = clazzType.getDeclaredMethods();

Method method = null;

for (Method m:ms) {

if(m.getName().equals(name)) {

method = m;

break;

}

}

printlnType(method.getGenericReturnType());

} catch (Exception e) {

e.printStackTrace();

}

}

public static void printlnMethodParamTypes(String name) {

System.out.println("name:"+name);

Class clazzType = TypeClazz.class;

try {

Method[] ms = clazzType.getDeclaredMethods();

Method method = null;

for (Method m:ms) {

if(m.getName().equals(name)) {

method = m;

break;

}

}

Type[] types = method.getGenericParameterTypes();

for (Type t:types) {

printlnType(t);

}

} catch (Exception e) {

e.printStackTrace();

}

}

对于属性,我们只关心它的类型,而对于方法,我们不仅需要关心它的参数类型,还要关心它的返回类型。我们来调用一下以上的信息:

public static void main(String ...args) {

printlnFieldType("member");

printlnFieldType("member2");

printlnFieldType("collection");

printlnFieldType("collection2");

printlnFieldType("array");

printlnMethodReturnType("method");

printlnMethodParamTypes("method");

}

控制台输出:

name:member

>>>TypeVariable

name:member2

>>>TypeVariable

name:collection

>>>ParameterizedType

>>>>>WildcardType

name:collection2

>>>ParameterizedType

>>>>>TypeVariable

name:array

>>>GenericArrayType

name:method

>>>class

name:method

>>>TypeVariable

>>>TypeVariable

对于直接采用泛型方式定义的member来说,它都是TypeVariable类型。而对于包含有泛型定义的collection来说,它属于参数化的ParameterizedType类型。由于数组类型是单独的类型,并且由虚拟机动态生成,因此,Type子类中有专门针对数组的GenericArrayType类型。例子中的array成员就是这种类型。我们揭开了collection的面纱后,泛型定义为" extends Number>"。这个就是通配符泛型WildcardType。

相信以上的例子已经很能解释这四种类型的定义了,下一篇,非墨将带着这些基础知识,深入到一个开源项目的源码中,看下别人的项目是如何巧妙的运用这点的。

java 泛型 type_轻触开源(一)-Java泛型Type类型的应用和实践相关推荐

  1. 轻触开源(一)-Java泛型Type类型的应用和实践

    2019独角兽企业重金招聘Python工程师标准>>> 转载请注明出处:https://my.oschina.net/u/874727/blog/747427 Q:102525062 ...

  2. 轻触开源(三)-Gson项目源码解析_贰

    2019独角兽企业重金招聘Python工程师标准>>> 转载请注明出处:https://my.oschina.net/u/874727/blog/750473 Q:102525062 ...

  3. 轻触开源(二)-Gson项目源码解析_壹

    2019独角兽企业重金招聘Python工程师标准>>> 上篇文章<轻触开源-Java泛型Type类型的应用和实践(一)> https://my.oschina.net/u ...

  4. java开源论坛(轻量开源论坛)

    Java开源UML建模是什么? Taylor MDA当前支持生成:EJB3 Entity BeansEJB3 Stateless Session Beans利用JBoss内置容器的JUnit Test ...

  5. java 获取泛型的type,如何获取泛型的Type类型

    开发中很多时候都遇到或使用到泛型.例如在json转换成bean对象或其他对象,而对象中存在泛型,这时候需要用到TypeToken. Type:是java里的 java.lang.reflect.Typ ...

  6. Java学习笔记(二一)——Java 泛型

    [前面的话] 最近脸好干,掉皮,需要买点化妆品了. Java泛型好好学习一下. [定义] 一.泛型的定义主要有以下两种: 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个 ...

  7. 陌陌安全开源了 Java 静态代码安全审计插件

    近日,陌陌安全开源了 Java 静态代码安全审计插件 MOMO Code Sec Inspector,侧重于在编码过程中发现项目潜在的安全风险,并提供一键修复能力. MOMO 安全团队认为,绝大部分 ...

  8. ali arthas 火焰图_带你上手阿里开源的 Java 诊断利器:Arthas

    本文适合有 Java 基础知识的人群. 本文作者:HelloGitHub-秦人 HelloGitHub 推出的<讲解开源项目>[1]系列,今天给大家带来一款阿里开源的 Java 诊断利器 ...

  9. java泛型的泛型_Java 泛型总结(一):基本用法与类型擦除

    简介 Java 在 1.5 引入了泛型机制,泛型本质是参数化类型,也就是说变量的类型是一个参数,在使用时再指定为具体类型.泛型可以用于类.接口.方法,通过使用泛型可以使代码更简单.安全.然而 Java ...

最新文章

  1. linux学习之VNC远程控制(一)
  2. c 语言文字输出函数,c/c++语言中文字输出函数总结
  3. PAT_B_1074 宇宙无敌加法器
  4. 关于金蝶k3 wise供应生门户登陆界面屏蔽业务账套多余功能模块设置方法
  5. go and git 代理
  6. 靠信用购物!芝麻信用上线新功能:用户可先用后买
  7. 实例化新的Android片段的最佳做法
  8. Tensorflow:分类模型评估
  9. spring beans 的类型
  10. Answer 3.0 .NET开源网站功能API说明
  11. 优先体验重播matlab_如何为深度Q网络实施优先体验重播
  12. ram计算机中术语,计算机术语 RAM ROM
  13. Word排版打印1寸照片
  14. python编程课件_Python面向对象程序设计ppt课件.ppt
  15. 开发isv应用的权限处理
  16. photoshop的抠图小结
  17. DSP2837x ECAP调试(BLDC霍尔)
  18. QT 代码行统计工具
  19. vue3 ref函数用法
  20. 学校计算机学院教学管理ER图,教学管理系统数据库ER图及SQL语句.doc

热门文章

  1. libcoap 接口分析与 CoAP 协议开发
  2. 数据概览神器—Pandas-profiling
  3. 十、Java接口——特殊的抽象类
  4. JimuReport - 积木报表(一款免费Web报表工具)
  5. python灰帽编程_灰帽Python的Python
  6. 【转】Axure RP 9 最新版授权码(亲测有效)
  7. CG迭代,CSR矩阵,cublas和cuspares加速
  8. 计算机counta函数怎么用,counta函数的使用方法及实例 看完你就知道了
  9. Pete's Pantry
  10. swing打地鼠游戏_经典街机游戏中的那些奖励关,为了得高分每次都被游戏厅老板吼...