Java Class类的简单用法

对于每一种类,Java虚拟机都会初始化一个Class类型的实例,当我们编译一个新的类就会产生一个Class对象,并且这个Class对象会被保存在同名的.class文件里。当我们new一个对象的时候,或者引用静态变量时,Java虚拟机的类加载器系统会将对应的Class对象加载到JVM中,然后JVM再根据这个Class相关的信息创建我们需要的实例对象或者提供静态变量的引用值。

获取class对象及部分信息的方法:

@Override
    protected void initView() {
        //获取class类的几种方式
        Log.i(TAG,"1 通过对象实例获取class==============================");
        Class stringClass = "abc".getClass();
        Log.i(TAG,"普通对象的class:" + stringClass);
        Log.i(TAG,"2 通过类的类型获取class==============================");
        Class easyTypeClass = int.class;
        Log.i(TAG,"基本类型的class:" + easyTypeClass);
        Class enumClass = E.A.getClass();
        Log.i(TAG,"enum类型的class:" + enumClass);
        Log.i(TAG,"3 通过类的全局限定名获取class==============================");
        try {
            Class nameClass = Class.forName("java.lang.String");
            Log.i(TAG,"通过全局限定名 java.lang.String 获取class: " + nameClass);
            Class cDoubleArrayClass = Class.forName("[D");
            Log.i(TAG,"通过全局限定名 [D 获取double[].class:" + cDoubleArrayClass);
            Class cStringArrayClass = Class.forName("[[Ljava.lang.String;");
            Log.i(TAG,"通过全局限定名 [[Ljava.lang.String; 获取String[][].class: " + cStringArrayClass);
            Log.i(TAG,"4 通过包装类的TYPE字段获取class==============================");
            Class doubleClass = Double.TYPE;
            Log.i(TAG,"基本类型的包装类也可以通过 TYPE字段获取Class:" + doubleClass);
            Log.i(TAG,"5 获取指定类的父类 class==============================");
            Class baseFraClass = BaseFragment.class;
            Log.i(TAG,"BaseFragment的Class对象: " + baseFraClass);
            Class baseFraFatherClass = baseFraClass.getSuperclass();
            Log.i(TAG,"BaseFragment的父类的Class对象: " + baseFraFatherClass);

            Log.i(TAG,"获取类的详细信息, 修饰符,类名,泛型类型,父类, 以hashMap类为例====================");
            Class hashMapClass = HashMap.class;
            Log.i(TAG,"hashMap 的 name为:" + hashMapClass.getName());
            Log.i(TAG,"hashMap 的 SimpleName为:" + hashMapClass.getSimpleName());
            Log.i(TAG,"hashMap 的 类修饰符为:" + Modifier.toString(hashMapClass.getModifiers()));

            TypeVariable[] tv = hashMapClass.getTypeParameters();
            StringBuilder pas = new StringBuilder();
            for (int i = 0; i < tv.length; i++) {
                TypeVariable t = tv[i];
                pas.append(t.getName() + "  ");
            }
            Log.i(TAG,"hashMap 的 泛型为:" + pas);

            Type[] ts = hashMapClass.getGenericInterfaces();
            StringBuilder genericInterface = new StringBuilder();
            for (int i = 0; i < ts.length; i++) {
                genericInterface.append(ts[i].toString() + "  ");
            }
            Log.i(TAG,"hashMap 的 实现接口, getGenericInterfaces :" + genericInterface);

            Type[] tss = hashMapClass.getInterfaces();
            StringBuilder interfaces = new StringBuilder();
            for (int i = 0; i < tss.length; i++) {
                interfaces.append(tss[i].toString() + "  ");
            }
            Log.i(TAG,"hashMap 的 实现接口, getInterfaces :" + interfaces);

            List<Class> fathers = new ArrayList<>();
            addAncestor(ReflexDemoAct.class, fathers);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < fathers.size(); i++) {
                Class c = fathers.get(i);
                builder.append(c.getCanonicalName() + "\n");
            }
            Log.i(TAG, "ReflexDemoAct 的继承树为 : \n" + builder.toString());

            Annotation[] annotations = ReflexDemoAct.class.getAnnotations();
            StringBuilder annotationString = new StringBuilder();
            if(null == annotations || annotations.length == 0){
                Log.i(TAG, "ReflectDemoAct类没有注解");
            } else {
                for (int i = 0; i < annotations.length; i++) {
                    Annotation annotation = annotations[i];
                    annotationString.append(annotation.toString() + "   ");
                }
                Log.i(TAG, "ReflectDemoAct类的Runtime类型的注解是: "+ annotationString.toString());
            }

            //以下是变量,方法,构造方法对应的类对应
            Log.i(TAG, Field.class.getCanonicalName() + ", 对应类的变量");
            Log.i(TAG, Method.class.getCanonicalName() + ", 对应类的方法");
            Log.i(TAG, Constructor.class.getCanonicalName() + ", 对应类的构造方法");

            Log.i(TAG, "但是,上面的方法正常情况下都不能获取private修饰的变量");
            Log.i(TAG, AccessibleObject.class.getCanonicalName() + ", 通过它的setAccessible()方法来取消Java语言访问权限的检查");
            Log.i(TAG, "很庆幸的是,Field, Method, Constructor方法均继承自AccessibleObject类,均可以设置这个入口,这样就可以访问private的内容了");

            Class reflexActClass = ReflexDemoAct.class;
            Field[] fields = reflexActClass.getFields();
            StringBuilder fieldBuild = new StringBuilder();
            for (int i = 0; i < fields.length; i++) {
               fieldBuild.append(fields[i].toString() + "\n");
            }
            Log.i(TAG, "得到的成员变量为: " + fieldBuild.toString());


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
private void addAncestor(Class<?> cla, List<Class> claList){
        Class<?> fatherCla = cla.getSuperclass();
        if (null != fatherCla){
            claList.add(fatherCla);
            addAncestor(fatherCla, claList);
        }
    }

Field

通过Field可以访问给定对象的类变量,仅对于当前类,不包含其父类里面的变量,包括获取变量的类型,修饰符,注解,变量的名,变量的值,或者重新设置变量值。即使变量是private的。Class类有4种获取Field的方式。

  • getDeclaredField(String name) 获取指定的变量(只要是声明的变量都能获得,即使是private的。)
  • getField(String name), 获取指定的变量(但是只能是public的)
  • deDeclaredFields(), 获取所有声明的变量,(包括private的)
  • getFields(),获取所有的public变量。
package com.example.forev.mycodelibrary;
import android.util.Log;
public class Cat {
    public static final String TAG = Cat.class.getSimpleName();
    private String name;
    @Deprecated
    public int age;

    public Cat(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String getName(){
        return name;
    }

    public void eat(String food){
        Log.d(TAG, "eat food " + food);
    }

    public void eat(String... foods){
        StringBuilder s = new StringBuilder();
        for(String food : foods){
            s.append(food);
            s.append(" ");
        }
        Log.d(TAG, "eat food " + s.toString());
    }

    public void sleep(){
        Log.d(TAG, "sleep");
    }

    @Override
    public String toString() {
        return "name = " + name + " age = " + age;
    }
}
private void logFieldUses() {
        Class reflexActClass = Cat.class;
        Field[] fields = reflexActClass.getDeclaredFields();
        StringBuilder fieldBuild = new StringBuilder();
        fieldBuild.append("\n");
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            fieldBuild.append("变量名:" + f.getName() + " ");
            fieldBuild.append("类型:" + f.getType() + " ");
            fieldBuild.append("修饰符:"+ Modifier.toString(f.getModifiers()) + " ");
            Annotation[] as = f.getAnnotations();
            if (null == as || as.length == 0){
                fieldBuild.append("没有注解\n");
            } else {
                for (int k = 0; k < as.length; k++) {
                    Annotation an = as[k];
                    fieldBuild.append("注解" + k + ":" + an.toString() + " ");
                }
            }

            fieldBuild.append("\n");
        }
        Log.i(TAG, "通过 getFields() 得到的public成员变量为: " + fieldBuild.toString());

        try {
            Cat cat = new Cat("yayali", 3);
            Field name = reflexActClass.getDeclaredField("name");
            //name是private类型的,所以要设置一下才可以访问。
            name.setAccessible(true);
            String nameValue = (String) name.get(cat);
            Log.i(TAG, "name的值为:" + nameValue);

            Field age = reflexActClass.getField("age");
            int ageValue = (int) age.get(cat);
            Log.i(TAG, "age的值为:" + ageValue);

            Field tag = reflexActClass.getField("TAG");
            String tagValue = (String) tag.get(cat);
            Log.i(TAG, "TAG的值为:" + tagValue);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

打印结果为:

2019-03-06 15:32:26.001 7835-7835/com.example.forev.mycodelibrary I/ReflexDemoAct: 通过 getFields() 得到的public成员变量为: 
    变量名:age 类型:int 修饰符:public 注解0:@java.lang.Deprecated() 
    变量名:name 类型:class java.lang.String 修饰符:private 没有注解
    
    变量名:TAG 类型:class java.lang.String 修饰符:public static final 没有注解
2019-03-06 15:32:26.001 7835-7835/com.example.forev.mycodelibrary I/ReflexDemoAct: name的值为:yayali
2019-03-06 15:32:26.001 7835-7835/com.example.forev.mycodelibrary I/ReflexDemoAct: age的值为:3
2019-03-06 15:32:26.001 7835-7835/com.example.forev.mycodelibrary I/ReflexDemoAct: TAG的值为:Cat

Method

代码如下:

private void logMethodUses(){
        Class catClass = Cat.class;
        Method[] methods = catClass.getDeclaredMethods();
        StringBuilder builder = new StringBuilder();
        builder.append("\n");
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            builder.append("方法名为:" + method.getName() + " ");
            builder.append("修饰符为:" + Modifier.toString(method.getModifiers()) + " ");
            builder.append("返回类型为:" + method.getGenericReturnType().toString() + " ");
            //方法抛出的异常
            Type[] exceptionTypes = method.getGenericExceptionTypes();
            if (0 == exceptionTypes.length){
                builder.append("没有异常! ");
            } else {
                builder.append("\"\\n 抛出的异常为:\\n\"");
                for (int k = 0; k < exceptionTypes.length; k++) {
                    Type type = exceptionTypes[k];
                    builder.append(type.toString() + "\n");
                }
            }

            //方法的参数,包括类型,名称,
            Type[] ptypes = method.getGenericParameterTypes();
            if (0 == ptypes.length){
                builder.append("没有参数! ");
            } else {
                builder.append("参数类型为:\n");
                for (int c = 0; c < ptypes.length; c++) {
                    Type type = ptypes[c];
                    builder.append(type.toString() + "\n");
                }
            }

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                Parameter[] params = method.getParameters();
                if (0 == params.length) {
                    builder.append(" 没有参数");
                } else {
                    for(int y = 0; y < params.length; y++) {
                        Parameter parameter = params[y];
                        String pName = parameter.getName();
                        String type = parameter.getType().toString();
                        builder.append(" 参数" + y + "的名字是:" + pName + " 类型是:" + type + "\n");
                    }
                }

            }

            //判断是否是可变参数
            builder.append(method.isSynthetic() ? "有可变参数! " : "没有可变参数! ");

            builder.append("\n");
        }

        Log.i(TAG, "method相关的信息为: " + builder.toString());

        Log.i(TAG, "\n 开始通过反射调用方法!");
        Cat cat = new Cat("huahua", 6);
        Method method = null;
        try {
            //重载机制的存在,我们得传入一个描述具体传什么类型的参数
            method = Cat.class.getMethod("eat", String.class);
            method.invoke(cat, "鱼干");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

打印日志:

2019-03-06 18:17:53.848 14929-14929/com.example.forev.mycodelibrary I/ReflexDemoAct: method相关的信息为: 
    方法名为:eat 修饰符为:public 返回类型为:void 没有异常! 参数类型为:
    class java.lang.String
     参数0的名字是:arg0 类型是:class java.lang.String
    没有可变参数! 
    方法名为:eat 修饰符为:public transient 返回类型为:void 没有异常! 参数类型为:
    class [Ljava.lang.String;
     参数0的名字是:arg0 类型是:class [Ljava.lang.String;
    没有可变参数! 
    方法名为:getName 修饰符为:public 返回类型为:class java.lang.String 没有异常! 没有参数!  没有参数没有可变参数! 
    方法名为:sleep 修饰符为:public 返回类型为:void 没有异常! 没有参数!  没有参数没有可变参数! 
    方法名为:toString 修饰符为:public 返回类型为:class java.lang.String 没有异常! 没有参数!  没有参数没有可变参数! 
2019-03-06 18:17:53.848 14929-14929/com.example.forev.mycodelibrary I/ReflexDemoAct:  开始通过反射调用方法!
2019-03-06 18:17:53.848 14929-14929/com.example.forev.mycodelibrary D/Cat: eat food 鱼干

Constructor 构造器

private void logConstructorUses(){
        Log.i(TAG, "测试构造方法!");
        try {
            Class catClass = Cat.class;
            Constructor constructor = catClass.getConstructor(String.class, int.class);
            Cat cat = (Cat) constructor.newInstance("黑猫警长", 12);

            Method sleepMethod = catClass.getMethod("sleep");
            sleepMethod.invoke(cat);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

打印日志为:

2019-03-06 18:27:43.162 15201-15201/com.example.forev.mycodelibrary I/ReflexDemoAct: 测试构造方法!
2019-03-06 18:27:43.162 15201-15201/com.example.forev.mycodelibrary D/Cat: sleep

猜你喜欢

转载自blog.csdn.net/weixin_28774815/article/details/88238378