反射使用(个人浅析)

一.反射定义:

反射机制是在运行状态中,对于任意一个类都可以通过反射调用其中的方法以及属性等。类的信息是保存在Class对象中的,而Class对象是ClassLoader动态加载的,当ClassLoader撞在了类以后,动态获取Class类的信息以及动态操作Class对象的方法和属性成为java的反射机制。

二.反射的基本使用如下面例子所示

注:注意看代码中的注释,标注了使用方法以及不同方法的区别,需要注意的都在注释中标注了!

  1. TestClass测试类
public class TestClass {
    public static void main(String[] args) throws ClassNotFoundException {
        reflectInvokeClass();
    }

    /**
     * 反射调用类的三种方式
     */
    private static void reflectInvokeClass()  {
        try {
            //一、获取class对象
            //1.第一种class.forName,会让ClassLoader装载类,并进行类的初始化
            Class class1 = Class.forName("com.garycong.java.MethodClass");

            //2.第二种getClass(),返回初始化后的对象
            Class class2 = new MethodClass().getClass();

            //3.第三种直接返回class,并ClassLoader装载入内存,但不做类的初始化
            Class class3 = MethodClass.class;
            //注:以下情况会抛出异常:
            //        1.当找不到指定的class时
            //        2.获取的变量不存在的时候或者由于权限问题没有获取到会抛出NoSuchFieldException异常


            //二、创建class对象
            //创建对象的时候可以以下分为无参和有参两种方式:
            //1.直接调用newInstance无参创建
            Object o = class1.newInstance();

            //2.拿到class1对应的Constructor对象,并入指定的参数类型,例如:int.class、String.class
            //  然后用拿到的Constructor对象调用newInstance并传入对应的参数
            Constructor<?> constructor = class1.getConstructor(int.class);
            Object o1 = constructor.newInstance(1);


            reflectInvokeMethod(class1);
            reflectInvokeField(class1);
            reflectInvokeConstuctor(class1);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.print("exception: " + e.getMessage());
        }

    }

    /**
     * 反射获取class的构造方法,注意修饰符不同的权限问题!!!
     * @param class1
     */
    private static void reflectInvokeConstuctor(Class class1) {
    }

    /**
     * 反射获取class的方法,注意修饰符不同的权限问题!!!
     * getMethod()只能反射调用public的方法,其他类型的会抛出异常
     * getDeclareMethod()可以调用public、private、protected的的方法
     * getMethods()只能反射调用指定类以及其父类的public的所有方法
     * getDeclareMethods()只能反射调用指定类的public、private、protected的所有方法
     *
     * 注:调用private和protected方法时,要设置setAccessible(true),绕过检查才可以调用!!!!
     * @param class1
     */
    private static void reflectInvokeMethod(Class class1) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Method publicMethod = class1.getMethod("publicMethod", int.class);
        Method publicMethod1 = class1.getDeclaredMethod("publicMethod", int.class);
//        Method privateMethod = class1.getMethod("privateMethod", int.class);getMethod()不能调用private,此处会抛出异常
        Method privateMethod = class1.getDeclaredMethod("privateMethod", int.class);
        Method protectedMethod = class1.getDeclaredMethod("protectedMethod", int.class);

        Object o = class1.newInstance();

        publicMethod1.invoke(o, 1);

        privateMethod.setAccessible(true);
        privateMethod.invoke(o, 1);

        protectedMethod.setAccessible(true);
        protectedMethod.invoke(o, 1);

        Method[] methods = class1.getMethods();
        Method[] declaredMethods = class1.getDeclaredMethods();
        System.out.print("MethodClass: reflectInvokeMethod, declaredMethods: " + Arrays.toString(declaredMethods) + " \n"
                + "methods:" + Arrays.toString(methods) + " \n"
                + "publicMethod: " + publicMethod + "\n"
                + "publicMethod1: " + publicMethod1 + "\n"
                + "privateMethod: " + privateMethod + "\n"
                + "protectedMethod: " + protectedMethod + "\n" );

        //获取静态类的方法,静态方法属于类的本身,所有invoke调用的时候第一个参数可以传null
        Method staticMethod = class1.getDeclaredMethod("staticMethod", int.class);
        staticMethod.invoke(null, 1);

    }

    /**
     * 反射获取class的变量,注意修饰符不同的权限问题!!!
     * getField()只能反射调用public的属性,其他类型的会抛出异常
     * getDeclareField()可以调用public、private、protected的的属性
     * getFields()只能反射调用指定类以及其父类的public的所有属性
     * getDeclareFields()只能反射调用指定类的public、private、protected的所有属性
     *
     * 注:调用private和protected属性时,要设置setAccessible(true),绕过检查才可以获取属性!!!!
     * @param class1
     */
    private static void reflectInvokeField(Class class1) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Field publicField = class1.getField("publicField");
        Field publicField1 = class1.getDeclaredField("publicField");
//        Method privateMethod = class1.getMethod("privateMethod", int.class);getMethod()不能调用private,此处会抛出异常
        Field privateField = class1.getDeclaredField("privateField");
        Field protectedField = class1.getDeclaredField("protectedField");

        Object o = class1.newInstance();
        publicField1.set(o, 1);

        privateField.setAccessible(true);
        privateField.set(o, 1);

        protectedField.setAccessible(true);
        protectedField.set(o, 1);

        Method[] methods = class1.getMethods();
        Method[] declaredMethods = class1.getDeclaredMethods();
        System.out.print("MethodClass: reflectInvokeField, declaredFields: " + Arrays.toString(declaredMethods) + " \n"
                + "Fields:" + Arrays.toString(methods) + " \n"
                + "publicField: " + publicField.get(o) + "\n"
                + "publicField1: " + publicField1.get(o) + "\n"
                + "privateField: " + privateField.get(o) + "\n"
                + "protectedField: " + protectedField.get(o) + "\n" );

        //获取静态类的方法,静态方法属于类的本身,所有invoke调用的时候第一个参数可以传null
//        Method staticMethod = class1.getDeclaredMethod("staticMethod", int.class);
//        staticMethod.invoke(null, 1);
    }
}

2.MethodClass反射调用的方法类

public class MethodClass {
    private static final String TAG = "MethodClass";

    public int publicField;
    private int privateField;
    protected int protectedField;

    public MethodClass() {
//        Log.i(TAG, "MethodClass: no param constructor");
        System.out.print("MethodClass: no param constructor \n");
    }
    public MethodClass(int i) {
//        Log.i(TAG, "MethodClass: one param constructor, i: " + i );
        System.out.print("MethodClass: one param constructor, i: " + i  + "\n");

    }

    public static void staticMethod(int i) {
        System.out.print("MethodClass: staticMethod, i: " + i + " \n");
    }

    public void publicMethod(int i) {
        System.out.print("MethodClass: publicMethod, i: " + i + " \n");

    }
    private void privateMethod(int i) {
        System.out.print("MethodClass: privateMethod, i: " + i + " \n");

    }
    protected void protectedMethod(int i) {
        System.out.print("MethodClass: protectedMethod, i: " + i + " \n");

    }
}

3.运行log如下:

MethodClass: no param constructor 
MethodClass: no param constructor 
MethodClass: one param constructor, i: 1
MethodClass: no param constructor 
MethodClass: publicMethod, i: 1 
MethodClass: privateMethod, i: 1 
MethodClass: protectedMethod, i: 1 
MethodClass: reflectInvokeMethod, declaredMethods: [public void com.garycong.java.MethodClass.publicMethod(int), private void com.garycong.java.MethodClass.privateMethod(int), protected void com.garycong.java.MethodClass.protectedMethod(int), public static void com.garycong.java.MethodClass.staticMethod(int)] 
methods:[public void com.garycong.java.MethodClass.publicMethod(int), public static void com.garycong.java.MethodClass.staticMethod(int), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()] 
publicMethod: public void com.garycong.java.MethodClass.publicMethod(int)
publicMethod1: public void com.garycong.java.MethodClass.publicMethod(int)
privateMethod: private void com.garycong.java.MethodClass.privateMethod(int)
protectedMethod: protected void com.garycong.java.MethodClass.protectedMethod(int)
MethodClass: staticMethod, i: 1 
MethodClass: no param constructor 
MethodClass: reflectInvokeField, declaredFields: [public void com.garycong.java.MethodClass.publicMethod(int), private void com.garycong.java.MethodClass.privateMethod(int), protected void com.garycong.java.MethodClass.protectedMethod(int), public static void com.garycong.java.MethodClass.staticMethod(int)] 
methods:[public void com.garycong.java.MethodClass.publicMethod(int), public static void com.garycong.java.MethodClass.staticMethod(int), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()] 
publicField: 1
publicField1: 1
privateField: 1
protectedField: 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值