Java反射中getGenericInterfaces和getInterfaces的解读

原创
2019/02/20 09:50
阅读数 8K

今天在做解析网络请求后得到的数据的转化的时候用到了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
    public void run() { }
    @Override
    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
    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
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部