Retrofit源码分析 (二.基础知识反射认识)

来源:互联网 发布:网络拓扑图 java 编辑:程序博客网 时间:2024/06/03 18:49

反射

反射位于java.lang.reflect包类,还是那句话,有兴趣的同学可以去瞅瞅,反正代码挺好看的。

下面主要讲的是这几个类,Method,Field,Type(子实现类GenericArrayType,WildcardType,TypeVariable,ParameterizedType)

当然有核心的类Class了,Proxy放在下一章讲。

1.java.lang.reflect.Array 动态创建数组的。示例如下:

        Object obg  = Array.newInstance(String.class,5);        Array.set(obg,0,"rulang0");        Array.set(obg,1,"rulang1");        String[] value = (String[])obg;        System.out.println(value[1]);//输出:rulang1

2.java.lang.reflect.Constructor 构造函数

/*        *********  _getConstructor()_ 和 _getDeclaredConstructor()_ 区别:*********        getDeclaredConstructor(Class<?>... parameterTypes)        这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。        getDeclaredConstructors()的返回结果就没有参数类型的过滤了。        再来看getConstructor(Class<?>... parameterTypes)        这个方法返回的是上面那个方法返回结果的子集,只返回制定参数类型访问权限是public的构造器。        getConstructors()的返回结果同样也没有参数类型的过滤。*/        Class<?> cls = Class.forName("com.rulang.reflect.RuLangDemo");        Constructor constructor1=cls.getConstructor(new Class[]{});        System.out.println("修饰符: "+ Modifier.toString(constructor1.getModifiers()));        System.out.println("构造函数名: "+constructor1.getName());        System.out.println("参数列表: "+constructor1.getParameterTypes());        Object obj = constructor1.newInstance();       // System.out.println("调用默认构造函数生成实例:"+obj.toString());//        Constructor constructor2 = cls.getConstructor(new Class[]{String.class});        Constructor constructor2 = cls.getDeclaredConstructor(new Class[]{String.class});//getConstructor        System.out.println("修饰符: "+Modifier.toString(constructor2.getModifiers()));        System.out.println("构造函数名: "+constructor2.getName());        System.out.println("参数列表: "+constructor2.getParameterTypes());        RuLangDemo obj2 = (RuLangDemo) constructor2.newInstance(new Object[]{"rulang"});        // Constructor constructor3 = cls.getDeclaredConstructor(new Class[]{String.class});  此处会抱错        Constructor constructor3 = cls.getDeclaredConstructor(new Class[]{int.class});        System.out.println("修饰符: "+Modifier.toString(constructor3.getModifiers()));        System.out.println("构造函数名: "+constructor3.getName());        System.out.println("参数列表: "+constructor3.getParameterTypes());        //下面的代码会抱错的,因为是私有构造函数,没法这样处理。        //RuLangDemo obj3 = (RuLangDemo) constructor3.newInstance(new Object[]{Integer.valueOf(999)});

输出的内容是:

修饰符: public构造函数名: com.rulang.reflect.RuLangDemo参数列表: [Ljava.lang.Class;@14ae5a5修饰符: public构造函数名: com.rulang.reflect.RuLangDemo参数列表: [Ljava.lang.Class;@6d6f6e28修饰符: private构造函数名: com.rulang.reflect.RuLangDemo参数列表: [Ljava.lang.Class;@135fbaa4
  1. java.lang.reflect.Field

    1.getDeclaredField(String name): 是可以获取一个类的其中一个字段

    2.getDeclaredFields():是可以获取一个类的所有字段

    3.getField(String name): 获取其中一个obj的字段

    4.getFields(): 主要是public字段所有的

    5.getType(): 获取属性声明时类型对象(返回class对象)

    6.getGenericType() : 返回属性声的Type类型

    7.getName() : 获取属性声明时名字

    8.getAnnotations() : 获得这个属性上所有的注释

    9.getModifiers() : 获取属性的修饰

    10.isEnumConstant() : 判断这个属性是否是枚举类

    11.isSynthetic() : 判断这个属性是否是 复合类

    12.get(Object obj) : 取得obj对象这个Field上的值

    13.set(Object obj, Object value) : 向obj对象的这个Field设置新值value

        RuLangDemo demo=new RuLangDemo();        System.out.println(demo.getmStr());//输出:xixi        Field field=demo.getClass().getDeclaredField("mStr");        field.setAccessible(true);        field.set(demo,"rulang");        System.out.println(demo.getmStr());//输出:rulang1

4.java.lang.reflect.Method

1.getMethods(): 获得类的public类型的方法2.getMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型3.getDeclaredMethods(): 获取类中所有的方法(public、protected、default、private)4.getDeclaredMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型
        RuLangDemo demo=new RuLangDemo();        System.out.println(demo.getmStr());//输出:xixi        Method setmStrMethod = demo.getClass().getMethod("setmStr", new Class[]{String.class});        System.out.println("修饰符: " + Modifier.toString(setmStrMethod.getModifiers()));        setmStrMethod.setAccessible(true); // 修饰符 如果是私有的,必须设置这个        setmStrMethod.invoke(demo, "rulang"); // 方法调用哦        System.out.println(demo.getmStr());//输出:rulang1

5.java.lang.reflect.Type

Type是所有类型的父接口, 如原始类型(raw types 对应 Class)、 参数化类型(parameterized types 对应 ParameterizedType)、 数组类型        (array types 对应 GenericArrayType)、 类型变量(type variables 对应 TypeVariable )基本(原生)类型(primitive types 对应 Class),。子接口有 ParameterizedType, TypeVariable, GenericArrayType, WildcardType, 实现类有Class。(1)ParameterizedType  是什么样的呢?    文档上有说明哦 ParameterizedType represents a parameterized type such as Collection<String>    Map<String, Object> map;    Set<String> set;    Class<?> class;    List<String> list;     这都是ParameterizedType类型哦    Type[] getActualTypeArguments(); Map<String,Object> map 这个ParameterizedType返回的是 String 类。    Object类的全限定类名的 Type Array。    Type getRawType()Map<String,Object> map 这个 ParameterizedType 返回的是 Map 类的全限定类名的 Type Array。    Type getOwnerType();Map<String,Object> map 这个 ParameterizedType 的 getOwnerType() 为 null,    而 Map.Entry<String,String> map 的 getOwnerType() 为 Map 所属于的 Type。
    public class Test {    private   Map<String,Object> map=null;    private   Map.Entry<String, String> map1=null;    public static void main(String[] jiexieQi) throws Exception {        Field map=Test.class.getDeclaredField("map");        Field map1=Test.class.getDeclaredField("map1");        ParameterizedType  mapType = (ParameterizedType) map.getGenericType();        ParameterizedType  map1Type = (ParameterizedType) map1.getGenericType();        System.out.println(mapType.getOwnerType());//输出:null        System.out.println(map1Type.getOwnerType());//输出:interface java.util.Map        System.out.println(mapType.getActualTypeArguments()[0]);//输出:class java.lang.String        System.out.println(mapType.getActualTypeArguments()[1]);//输出:class java.lang.Object    }
(2)TypeVariable:是各种类型变量的公共父接口,就是泛型里面的类似T、E。     TypeVariable,类型变量,描述类型,表示泛指任意或相关一类类型,也可以说狭义上的泛型(泛指某一类类型),    一般用大写字母作为变量,比如K、V、E等
    TypeVariable 源码如下:    public interface TypeVariable<D extends GenericDeclaration> extends Type {           //获得泛型的上限,若未明确声明上边界则默认为Object            Type[] getBounds();            //获取声明该类型变量实体(即获得类、方法或构造器名)            D getGenericDeclaration();            //获得名称,即K、V、E之类名称            String getName();    }
(3)GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型,比如List<>[],T[]这种。
public class Test {    private  List<String> [] listArray; //GenericArrayType 转为Class哦    public static void main(String[] jiexieQi) throws Exception {        Field listArray=Test.class.getDeclaredField("listArray");        Type typeList=listArray.getGenericType();        GenericArrayTypeImpl ty= (GenericArrayTypeImpl) typeList;        ParameterizedType uu= (ParameterizedType) ty.getGenericComponentType();        System.out.println(uu.getTypeName());//输出:java.util.List<java.lang.String>    }
(4)WildcardType:代表一种通配符类型表达式,类似? super T这样的通配符表达式。
源码如下:public interface WildcardType extends Type {    //获得泛型表达式上界(上限)    Type[] getUpperBounds();    //获得泛型表达式下界(下限)    Type[] getLowerBounds();}
public <T> void test(List<? extends classA > a){}Method method = Main.class.getMethod("test",List.class);        Type[] upperBounds = null;        Type[] lowerBounds = null;        Type[] types = method.getGenericParameterTypes();        for(Type type : types){        Type[] actualTypeArgument = ((ParameterizedType)type).getActualTypeArguments();            for(Type t : actualTypeArgument){                WildcardType wildcardType = (WildcardType) t;                lowerBounds = wildcardType.getLowerBounds();                upperBounds = wildcardType.getUpperBounds();                System.out.println("通配符表达式类型是:"+ wildcardType);                if(upperBounds.length != 0){                    System.out.println("表达式上边界:"+Arrays.asList(upperBounds));                    }                if(lowerBounds.length != 0){                    System.out.println("表达式下边界:"+Arrays.asList(lowerBounds));                    }            }        }//输出结果通配符表达式类型是:? extends com.fcc.test.classA表达式上边界:[class com.fcc.test.classA]

次章结束,下一章将Proxy讲一下之后,将讲Retrofit源码分析。

原创粉丝点击