HashMap.comparableClassFor(Object x)方法解读:类型/泛型相关方法
来源:互联网 发布:sql查询用户名和密码 编辑:程序博客网 时间:2024/06/17 15:37
- 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; }
阅读全文
0 0
- HashMap.comparableClassFor(Object x)方法解读:类型/泛型相关方法
- HashMap里hash方法解读
- HashMap 主要特点和关键方法源码解读
- HashMap的get方法为空解读
- HashMap中get(Object key)方法实现
- 解读Object类的equals方法
- object类中相关方法
- javascript-Object类型的方法
- String类型相关方法
- HashMap中的put(Object key, Object value)方法实现
- Object-c 常用类型定义方法
- JAVA 的 OBJECT 类型转 INT 方法
- js中object类型中的三个方法
- javascript之Object类型属性、方法
- object类型转string类型(的三种方法)
- object类型强制转换成Int类型的方法
- 将Object类型转成String类型的几种方法
- Object方法
- 欢迎使用CSDN-markdown编辑器
- freemark常用
- java中charAt()与toCharArray(),indexOf的综合使用
- windows下使用PHP实现定时执行脚本
- git add详解(总记不住啥时候用add的哪个参数、囧)
- HashMap.comparableClassFor(Object x)方法解读:类型/泛型相关方法
- 通过js使用动画曲线
- Fox And Two Dots
- 异常点检测
- Meta标签总结
- Kylin建立cube时报错
- 1009. Product of Polynomials (25)
- java中常用的时间处理类TimeUtil
- 数据库建模工具(包含开源版)