V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  Java

为毛 HashMap 里 comparableClassFor 方法要判断 p.getActualTypeArguments()返回的数组大小呢?

  •  1
     
  •   amiwrong123 · 2019-12-07 19:23:52 +08:00 · 2535 次点击
    这是一个创建于 1848 天前的主题,其中的信息可能已经有所发展或是发生改变。
        static Class<?> comparableClassFor(Object x) {
            if (x instanceof Comparable) { // 首先检查 x 是否可以转型为 Comparable
                Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
                if ((c = x.getClass()) == String.class) // 如果类型是 String 则直接返回,因为 String 是泛型自限定的
                    return c;
                if ((ts = c.getGenericInterfaces()) != null) {
                    for (int i = 0; i < ts.length; ++i) {
                        if (((t = ts[i]) instanceof ParameterizedType) &&
                            ((p = (ParameterizedType)t).getRawType() ==
                             Comparable.class) &&
                            (as = p.getActualTypeArguments()) != null &&
                            as.length == 1 && as[0] == c) // type arg is c
                            return c;
                    }
                }
            }
            return null;
        }
    

    这个函数里的逻辑大概都看懂了,就一个地方,为什么一定要加 as.length == 1 呢?

    • ((t = ts[i]) instanceof ParameterizedType),通过了这个判断,说明肯定是泛型接口了,而且类定义里尖括号里面有东西。(这个我试过,如果继承了 Comparable 的原生类型,那么它的 Type 就不是 ParameterizedType 的实例了)。
    • (p = (ParameterizedType)t).getRawType() == Comparable.class),通过了这个判断,说明是 Comparable 接口。
    • as[0] == c,通过了这个判断,说明类型参数就是它本身,即泛型自限定了。

    我想之所以要判断 as.length == 1,是因为 length 确实可能为 0,但如果前面的判断都通过了,那就说明尖括号肯定有东西了啊,而且 Comparable 的接口定义里,类型参数就一个啊,那就直接 as[0] == c 就好了啊,不用判断 as.length == 1 了啊?

    还是说真的有那种情况,就算前面的判断都通过了,as.length 还是可能为 0 吗?

    2 条回复    2019-12-19 10:00:43 +08:00
    qwerthhusn
        1
    qwerthhusn  
       2019-12-09 15:04:27 +08:00
    Java 5 之后类型系统就变得极其复杂了、、、、

    我估计是为了应对 Java 字节码增强的那些技术吧,我不知道那些字节码增强能不能改动 jdk 内部的类。。。

    正常情况下,如果 Type 是 ParameterizedType,getActualTypeArguments 应该不会返回 null 的。RawType 是 Comparable,,,getActualTypeArguments 数组长度也该是 1

    我们自己写可能就变成了这样
    if ((t instanceof ParameterizedType) &&
    ((p = (ParameterizedType)t).getRawType() == Comparable.class) &&
    p.getActualTypeArguments()[0] == c)
    amiwrong123
        2
    amiwrong123  
    OP
       2019-12-19 10:00:43 +08:00
    @qwerthhusn
    不知道为啥我没看见你的回复提醒。。。

    确实复杂,我当时看这段代码看了好久。。

    算了,as.length == 1 这里虽然有点多余,但是显得很严谨,哈哈哈哈。

    你说的字节码增强,难道说有可能改变 Comparable 的接口定义,使得尖括号里面的类型参数变成两个或者更多吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1925 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 00:43 · PVG 08:43 · LAX 16:43 · JFK 19:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.