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 吗?