文档章节

Java反射中getGenericInterfaces和getInterfaces的解读

落叶挽歌
 落叶挽歌
发布于 02/20 09:50
字数 1007
阅读 69
收藏 0

今天在做解析网络请求后得到的数据的转化的时候用到了getGenericInterfaces这个方法,顺便也了解了下和他长得差不多的getInterfaces方法。

官方文档解释

getGenericInterfaces:

Returns the {@code Type}s representing the interfaces directly implemented by the class or interface represented by this object.释意:返回表示由此对象表示的类或接口直接实现的接口的{@code Type}。

getInterfaces:

Determines the interfaces implemented by the class or interface represented by this object. 释意:返回由此对象表示的类或接口实现的接口。

从解释上面来看出来了,差异在于“接口实现的接口的Type”,接下来用具体示例来解释区别

private class Food{
    String foodName;
}
private interface Eat{
    void eat(String things);
}
private interface Run{
    void run();
}
private class Dog implements Eat,Run{
    [@Override](https://my.oschina.net/u/1162528)
    public void run() { }
    [@Override](https://my.oschina.net/u/1162528)
    public void eat(String things) { }
}
private void main() {
    Class<?> clazz = Dog.class;
    Type[] genericInterfaces = clazz.getGenericInterfaces();
    Class<?>[] interfaces = clazz.getInterfaces();
}

运行结果:

我们可以看到,clazz.getGenericInterfaces()与clazz.getInterfaces()并没有任何差异。因为 并没有:“实现的接口的Type”

接下来看另一段代码,我们对Eat接口改造一下,增加参数化类型

private class Food{
    String foodName;
}
private interface Eat<T>{
    void eat(T things);
}
private interface Run{
    void run();
}

private class Dog implements Eat<Food>,Run{
    [@Override](https://my.oschina.net/u/1162528)
    public void run() { }
    @Override
    public void eat(Food things) { }
}
private void main() {
    Class<?> clazz = Dog.class;
    Type[] genericInterfaces = clazz.getGenericInterfaces();
    Class<?>[] interfaces = clazz.getInterfaces();
}

运行结果:

可以看到:clazz.getGenericInterfaces();所生成的数组里有一个接口类型为:ParameterizedType 而ParameterizedType extends Type 而ParameterizedType 和 Type 有什么区别呢?

Type代表 包括原始类型,参数化类型、数组类型、类型变量和原始类型,而ParameterizedType只代表参数化类型 官方文档:

ParameterizedType represents a parameterized type such as Collection<String>

译:ParameterizedType表示参数化类型,例如 Collection<String> ParameterizedType相对于Type新增了三个接口方法:

  • Type[] getActualTypeArguments(); //返回参数化类型的实际类型的数组 例如:Food<Fruit,Vegetable>那么将返回 [Fruit,Vegetable]这两个类型的数组 下面两种方法就不用多说了,从字面意思就能看出来。

  • Type getRawType();

  • Type getOwnerType();

回到上面,在看getGenericInterfaces()的内部实之前现,我们先看看getInterfaces()的内部实现

public Class<?>[] getInterfaces() {
    if (isArray()) {
        return new Class<?>[] { Cloneable.class, Serializable.class };
    }
    final Class<?>[] ifaces = getInterfacesInternal();
    if (ifaces == null) {
        return EmptyArray.CLASS;
    }
    return ifaces;
}
@FastNative
private native Class<?>[] getInterfacesInternal();

可以看到,getInterfaces源码逻辑比较简单先判断传入的是不是一个class 数组,我们这里先对单个class进行讨论,暂且不管,后面使用了native方法getInterfacesInternal

再看getGenericInterfaces()的内部实现

  public Type[] getGenericInterfaces() {
    Type[] result;
    synchronized (Caches.genericInterfaces) {
        result = Caches.genericInterfaces.get(this);
        if (result == null) {
            String annotationSignature = getSignatureAttribute();
            if (annotationSignature == null) {
                result = getInterfaces();
            } else {
                GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
                parser.parseForClass(this, annotationSignature);
                result = Types.getTypeArray(parser.interfaceTypes, false);
            }
            Caches.genericInterfaces.put(this, result);
        }
    }
    return (result.length == 0) ? result : result.clone();
}`

内部实现完全和getInterfaces()不太一样 逻辑是:

1、从缓存中取genericInterfaces

2、没有再利用 getSignatureAttribute(),先不管getSignatureAttribute具体做了什么,从字面意思上看是获取了相关属性

3、getSignatureAttribute值为null则执行 getInterfaces,否则继续获取 4、缓存数据

其实这里我们已经能明白getInterfaces和getGenericInterfaces的差异性了,主要在getSignatureAttribute()这里,接下来继续对getSignatureAttribute()进行分析

getSignatureAttribute()的内部实现为:

private String getSignatureAttribute() {
    String[] annotation = getSignatureAnnotation();
    if (annotation == null) {
        return null;
    }
    StringBuilder result = new StringBuilder();
    for (String s : annotation) {
        result.append(s);
    }
    return result.toString();
}

最主要看getSignatureAnnotation(),这又是一个native方法,这个之后再进行详细讲解。

对上面的内容进行一个总结:

getInterfaces:主要是 获取由此对象表示的类或接口实现的接口

getGenericInterfaces: 主要是 获取由此对象表示的类或接口直接实现的接口的Type。

区别在于getGenericInterfaces可以返回其参数化类型,例如: Collection<String>、 List<Coupon>中的String和Coupon

小的才疏学浅,难免有些地方会有错误,欢迎指正。

© 著作权归作者所有

落叶挽歌

落叶挽歌

粉丝 0
博文 35
码字总数 19836
作品 0
温州
Android工程师
私信 提问
RTTI VS Reflection

1.RTTI( Run-Time Type Information) RTTI( Run-Time Type Information)的主要作用就是运行期鉴定对象的类型,比如需要塑形的时候,使用instanceof判断类型的时候。Java用Class对象实现自...

enosh
2014/12/25
104
0
动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

在运行时期可以按照Java虚拟机规范对class文件的组织规则生成对应的二进制字节码。当前有很多开源框架可以完成这些功能,如ASM,Javassist。 动态代理机制详解(JDK 和CGLIB,Javassist,ASM...

素雷
2017/10/19
113
0
PerfMa给OpenJDK社区提交的第一个Patch

概述 前两天给openjdk gc-dev的email list提交了一个问题,主要是针对Full GC之后,GC日志里Metaspace的大小在GC前后都一直不变的问题,我在邮件里大概也提了下如何修复该问题,以及猜测了下...

你假笨
2018/09/25
0
0
Java面试基础篇——第十五篇:代理模式

什么是代理? 通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理。 代理应用场景 安全代理 可以屏蔽真实角色远程代理 远程调用代理类RMI延迟加载 先加载...

developlee的潇洒人生
2018/08/02
111
0
升级到JDK9的一个BUG,你了解吗

概述 前几天在一个群里看到一个朋友发了一个demo,说是JDK的bug,昨天在JVM的一个群里又有朋友发了,觉得挺有意思,分享给大家,希望大家升级JDK的版本的时候注意下是否存在这样的代码,如果...

你假笨
2018/06/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0
轻量级 HTTP(s) 代理 TinyProxy

CentOS 下安装 TinyProxy yum install -y tinyproxy 启动、停止、重启 # 启动service tinyproxy start# 停止service tinyproxy stop# 重启service tinyproxy restart 相关配置 默认...

Anoyi
昨天
2
0
Linux创建yum仓库

第一步、搞定自己的光盘 #创建文件夹 mkdir -p /media/cdrom #挂载光盘 mount /dev/cdrom /media/cdrom #编辑配置文件使其永久生效 vim /etc/fstab 第二步,编辑yun源 vim /ect yum.repos.d...

究极小怪兽zzz
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部