HashMap.comparableClassFor(Object x)方法解读:类型/泛型相关方法

  • HashMap.comparableClassFor(Object x)
  • instanceof
  • getClass()
  • getGenericInterfaces()
  • getGenericSuperclass()和getSuperclass()
  • ParameterizedType
  • getRawType()
  • getActualTypeArguments()
  • getOwnerType()
  • comparableClassFor(Object x)方法总结

HashMap.comparableClassFor(Object x)

HashMap类中有一个comparableClassFor(Object x)方法,当x的类型为X,且X直接实现了Comparable接口(比较类型必须为X类本身)时,返回x的运行时类型;否则返回null。通过这个方法,我们可以搞清楚一些与类型、泛型相关的概念和方法。

先看一下例子。由于没法直接调用HashMap.comparableClassFor(Object x),我们将这个方法复制出来。

public class Demo {
    public static void main(String[] args) {
        System.out.println(comparableClassFor(new A()));    // null,A does not implement Comparable.
        System.out.println(comparableClassFor(new B()));    // null,B implements Comparable, compare to Object.
        System.out.println(comparableClassFor(new C()));    // class Demo$C,C implements Comparable, compare to itself.
        System.out.println(comparableClassFor(new D()));    // null,D implements Comparable, compare to its sub type.
        System.out.println(comparableClassFor(new F()));    // null,F is C's sub type.
    }

    static class A{}
    static class B implements Comparable<Object>{
        @Override
        public int compareTo(Object o) {return 0;}
    }
    static class C implements Comparable<C>{
        @Override
        public int compareTo(C o) {return 0;}

    }
    static class D implements Comparable<E>{
        @Override
        public int compareTo(E o) {return 0;}
    }
    static class E{}
    static class F extends C{}

    /**
     * Returns x's Class if it is of the form "class C implements
     * Comparable<C>", else null.
     */
    static Class<?> comparableClassFor(Object x) {
        if (x instanceof Comparable) {
            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
            if ((c = x.getClass()) == String.class) // bypass checks
                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;
    }
}

结果与注释描述的一致,只有当传入对象的运行时类型符合”class C implements Comparable”这个条件时,返回对象的运行时类型,否则返回null。下面看一下这个方法的过程。


instanceof
x instanceof Comparable
  • insanceof可以理解为是某种类型的实例,无论是运行时类型,还是它的父类,它实现的接口,他的父类实现的接口,甚至它的父类的父类的父类实现的接口的父类的父类,总之,只要在继承链上有这个类型就可以了。

getClass()
c = x.getClass()
  • 与instanceof相应对的是getClass()方法,无论该对象如何转型,getClass()返回的只会是它的运行时类型,可以简单的理解为它的实际类型,也就是new它的时候的类型。
    有一种例外情况,匿名对象。当匿名对象调用getClass()时返回的是依赖它的对象的运行时类型,并以1,2,3…的索引区分。
public class Demo {
    public static void main(String[] args) {
        D d = new D();
        System.out.println(new A(){}.getClass());   // class Demo$1
        System.out.println(new B(){}.getClass());   // class Demo$2
        System.out.println(new Comparable<Object>(){    // class Demo$3
            @Override
            public int compareTo(Object o) {
                return 0;
            }}.getClass());
        System.out.println(d.c.getClass()); // class D$1
    }
}

abstract class A{}
abstract class B{}
abstract class C{}
class D{
    C c;
    D(){
        c= new C(){};
    }
}

getGenericInterfaces()
ts = c.getGenericInterfaces()
  • getGenericInterfaces()方法返回的是该对象的运行时类型“直接实现”的接口,这意味着:
    • 返回的一定是接口。
    • 必然是该类型自己实现的接口,继承过来的不算。
public class Demo {
    public static void main(String[] args) {
        Grand child = new Child();
        Type[] types = child.getClass().getGenericInterfaces();
        if (types != null) {
            for (Type type : types) {
                System.out.println(type.getTypeName());
            }
        }
    }
}

abstract class Grand implements Comparable<Grand>{}
abstract class Super extends Grand implements Serializable{}
class Child extends Super implements Cloneable {public int compareTo(Grand o) {return 0;}}

getGenericSuperclass()和getSuperclass()
  • 这两个方法虽然没有出现在comparableClassFor(Object x)中,这里也顺便看一下。通过简单的例子,可以看到:
    • getSuperclass()返回的是直接父类的类型,不包括泛型参数。
    • getGenericSuperclass()返回的是包括泛型参数在内的直接父类。
    • 注意如果父类声明了泛型,但子类继承时没有为父类实现该泛型,这时候也是没有泛型参数的。
public class Demo {
    public static void main(String[] args) {
        Grand child = new Child();
        Type type1 = child.getClass().getGenericSuperclass();
        Class<?> class1 = child.getClass().getSuperclass();
        System.out.println(type1.getTypeName());    // Super<java.lang.Integer, java.lang.Integer>
        System.out.println(class1.getTypeName());   // Super

        Grand child2 = new Child2();
        Type type2 = child2.getClass().getGenericSuperclass();
        Class<?> class2 = child2.getClass().getSuperclass();
        System.out.println(type2.getTypeName());    // test.Super<A, B>
        System.out.println(class2.getTypeName());   // Super

        Grand child3 = new Child3();
        Type type3 = child3.getClass().getGenericSuperclass();
        Class<?> class3 = child3.getClass().getSuperclass();
        System.out.println(type3.getTypeName());    // Super
        System.out.println(class3.getTypeName());   // Super
    }
}
abstract class Grand implements Comparable<Grand>{}
abstract class Super<T,E> extends Grand implements Serializable{}
class Child extends Super<Integer,Integer> implements Cloneable {public int compareTo(Grand o) {return 0;}}
class Child2<A,B,C> extends Super<A,B>{public int compareTo(Grand o) {return 0;}}
class Child3 extends Super{public int compareTo(Grand o) {return 0;}}

ParameterizedType
((t = ts[i]) instanceof ParameterizedType)
  • ParameterizedType是Type接口的子接口,表示参数化的类型,即实现了泛型参数的类型。需要注意:
    • 如果直接用bean对象instanceof ParameterizedType,结果都是false。
    • Class对象不能instanceof ParameterizedType,编译会报错。
    • 只有用Type对象instanceof ParameterizedType才能得到想要的比较结果。可以这么理解:一个Bean类不会是ParameterizedType,只有代表这个Bean类的类型(Type)才可能是ParameterizedType。
    • 实现泛型参数,可以是给泛型传入了一个真实的类型,或者传入另一个新声明的泛型参数;只声明泛型而不实现,instanceof ParameterizedType为false。
public class Demo {
    public static void main(String[] args) {
        Grand child1 = new Child();
        Grand child2_1 = new Child2();
        Grand child2_2 = new Child2<String, String>();
        Child2<String, String> child2_3 = new Child2<String, String>();
        Child3<String, String> child3 = new Child3<String,String>();
        System.out.println(child1 instanceof ParameterizedType);    // flase
        System.out.println(child2_1 instanceof ParameterizedType);  // flase
        System.out.println(child2_2 instanceof ParameterizedType);  // flase
        System.out.println(child2_3 instanceof ParameterizedType);  // flase
        System.out.println(child1.getClass().getGenericSuperclass() instanceof ParameterizedType);  // true
        System.out.println(child2_1.getClass().getGenericSuperclass() instanceof ParameterizedType);    // true
        System.out.println(child3.getClass().getGenericSuperclass() instanceof ParameterizedType);  // flase
        // System.out.println(child1.getClass() instanceof ParameterizedType);  // Complie Errors
    }
}
class Grand{}
class Super<A,B> extends Grand{}
class Child extends Super<String,String>{}
class Child2<A,B> extends Super<A,B>{}
class Child3<A,B> extends Super{}
public class Demo {
    public static void main(String[] args) {
        Grand grand = new Grand();
        Type[] types = grand.getClass().getGenericInterfaces();
        if (types != null) {
            for (Type type : types) {
                System.out.println(type.getTypeName() + " " + (type instanceof ParameterizedType));
                // Output result:
                //IA<java.lang.String, java.lang.Integer> true
                //IB false
                //IC<X> true
                //ID false
            }
        }
    }
}
interface IG<X,Y>{}
interface IA<X,Y>{}
interface IB extends IG{}
interface IC<X>{}
interface ID<X>{}
class Grand<X> implements IA<String,Integer>,IB,IC<X>,ID{}

getRawType()
(p = (ParameterizedType)t).getRawType()
  • getRawType()方法返回声明了这个类型的类或接口,也就是去掉了泛型参数部分的类型对象。
public class Demo {
    public static void main(String[] args) {
        Grand grand = new Grand();
        Type[] types = grand.getClass().getGenericInterfaces();
        if (types != null) {
            for (Type type : types) {
                if(type instanceof ParameterizedType){
                    System.out.println(((ParameterizedType) type).getRawType());
                    // Output result:
                    // interface test.IA
                    // interface test.IC
                }
            }
        }
    }
}
interface IG<X,Y>{}
interface IA<X,Y>{}
interface IB extends IG{}
interface IC<X>{}
interface ID<X>{}
class Grand<X> implements IA<String,Integer>,IB,IC<X>,ID{}

getActualTypeArguments()
(as = p.getActualTypeArguments())
  • 与getRawType()相对应,getActualTypeArguments()以数组的形式返回泛型参数列表。
  • 注意,这里返回的是实现该泛型时传入的参数,可以看下方代码的打印结果:
    • 当传入的是真实类型时,打印的是全类名。
    • 当传入的是另一个新声明的泛型参数时 ,打印的是代表该泛型参数的符号。
public class Demo {
    public static void main(String[] args) {
        Grand grand = new Grand();
        Type[] types = grand.getClass().getGenericInterfaces();
        if (types != null) {
            for (Type type : types) {
                if(type instanceof ParameterizedType){
                    System.out.println(type.getTypeName());
                    Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
                    if(typeArguments != null){
                        for (Type typeArg : typeArguments) {
                            System.out.println(typeArg.getTypeName());
                            // Output result:
                            // IA<java.lang.String, java.lang.Integer>
                            // java.lang.String
                            // java.lang.Integer
                            // IC<X>
                            // X
                        }
                    }
                }
            }
        }
    }
}
interface IG<X,Y>{}
interface IA<X,Y>{}
interface IB extends IG{}
interface IC<X>{}
interface ID<X>{}
class Grand<X> implements IA<String,Integer>,IB,IC<X>,ID{}

getOwnerType()
  • ParameterizedType接口还有一个getOwnerType()方法,如果该类型是一个内部类/接口,返回它的外部类/接口。如果该类型不是内部类/接口,返回null。
public class Demo {
    public static void main(String[] args) {
        Outer<String> outer = new Outer<>();
        Outer<String>.Child<Integer> child = outer.new Child<>();
        Type type = child.getClass().getGenericSuperclass();
        if(type instanceof ParameterizedType){
            System.out.println(((ParameterizedType) type).getOwnerType()); //Outer<X>
        }
    }
}

class Outer<X>{
    class Inner<Y>{}
    class Child<Y> extends Inner<Y>{}
}

comparableClassFor(Object x)方法总结
 static Class<?> comparableClassFor(Object x) {
        if (x instanceof Comparable) {  // 判断是否实现了Comparable接口
            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
            if ((c = x.getClass()) == String.class) 
                return c;   // 如果是String类型,直接返回String.class
            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) &&   //  该类型是Comparable
                        (as = p.getActualTypeArguments()) != null &&    // 获取泛型参数数组
                        as.length == 1 && as[0] == c)   // 只有一个泛型参数,且该实现类型是该类型本身
                        return c;   // 返回该类型
                }
            }
        }
        return null;
    }

转载于:https://www.cnblogs.com/leeqihe/p/9061175.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值