溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java反射技術(shù)怎么用

發(fā)布時(shí)間:2021-11-08 17:46:43 來源:億速云 閱讀:388 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了“Java反射技術(shù)怎么用”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Java反射技術(shù)怎么用”這篇文章吧。

    一、基本反射技術(shù)

    1.1 根據(jù)一個(gè)字符串得到一個(gè)類

    getClass方法
     String name = "Huanglinqing";
     Class c1 = name.getClass();
     System.out.println(c1.getName());

    打印結(jié)果如下:

    Java反射技術(shù)怎么用

    Class.forName

    比如我們獲取java.lang.String的類名

       String name = "java.lang.String";
       Class c1 = null;
       try {
              c1 = Class.forName(name);
              System.out.println(c1.getName());
          } catch (ClassNotFoundException e) {
      }

    這里也通過捕獲異常,因?yàn)槲覀儌鞯倪@個(gè)字符串可能不合法,字符串合法命名是類的命名空間和類的名稱組成

    打印結(jié)果如下:

    Java反射技術(shù)怎么用

    我們還可以通過c1.getSuperclass()獲取到他的父類

    Type屬性

    基本類型都有type屬性,可以得到這個(gè)基本類型的類型,比如:

    Class c1 = Boolean.TYPE;
    Class c2 = Byte.TYPE;
    Class c3 = Float.TYPE;
    Class c4 = Double.TYPE;

    二、獲取類的成員

    當(dāng)類中方法定義為私有的時(shí)候我們能調(diào)用?不能!當(dāng)變量是私有的時(shí)候我們能獲取嗎?不能!但是反射可以,比如源碼中有你需要用到的方法,但是那個(gè)方法是私有的,這個(gè)時(shí)候你就可以通過反射去執(zhí)行這個(gè)私有方法,并且獲取私有變量。

    獲取類的構(gòu)造函數(shù)

    為了便于測試,我們定義一個(gè)Test類,Test類如下:(省略get和set方法)

    Test類中我們定義是三個(gè)私有變量,生成兩個(gè)公有的含參構(gòu)造方法和一個(gè)私有的含參構(gòu)造方法以及一個(gè)公有的無參構(gòu)造方法。

    public class Test {
        private int age;
        private String name;
        private int testint;
        public Test(int age) {
            this.age = age;
        }
        public Test(int age, String name) {
            this.age = age;
            this.name = name;
        }
        private Test(String name) {
            this.name = name;
        }
        public Test() {
        }

    下面我們通過反射獲取這些構(gòu)造方法

    獲取類的所有構(gòu)造方法

     Test test = new Test();
     Class c4 = test.getClass();
     Constructor[] constructors ;
     constructors = c4.getDeclaredConstructors();

    通過getDeclaredConstructors可以返回類的所有構(gòu)造方法,返回的是一個(gè)數(shù)組因?yàn)闃?gòu)造方法可能不止一個(gè),通過getModifiers可以得到構(gòu)造方法的類型,getParameterTypes可以得到構(gòu)造方法的所有參數(shù),返回的是一個(gè)Class數(shù)組,所以我們?nèi)绻氆@取所有構(gòu)造方法以及每個(gè)構(gòu)造方法的參數(shù)類型,可以有如下代碼:

      for (int i = 0; i < constructors.length; i++) {
            System.out.print(Modifier.toString(constructors[i].getModifiers()) + "參數(shù):");
            Class[] parametertypes = constructors[i].getParameterTypes();
            for (int j = 0; j < parametertypes.length; j++) {
                 System.out.print(parametertypes[j].getName() + " ");
           }
          System.out.println("");
      }

    運(yùn)行結(jié)果如下所示:

    Java反射技術(shù)怎么用

    這樣我們就得到了類中所有構(gòu)造方法和構(gòu)造方法中的參數(shù),那么我們?nèi)绾潍@取特定的構(gòu)造方法呢?

    獲取類中特定的構(gòu)造方法

    我們可以通過getConstructors方法獲取類中 所有的public類型的構(gòu)造方法,代碼和上面一樣就不演示了。

    我們可以通過getDeclaredConstructor()方法傳參獲取特定參數(shù)類型的構(gòu)造方法,這里注意是getDeclaredConstructor()不是 getDeclaredConstructors() ,所以返回的是一個(gè)Class對象而不是一個(gè)Class數(shù)組。

    獲取無參構(gòu)造方法直接不傳參數(shù),如下所示:

       try {
              constructors = c4.getDeclaredConstructor();
              System.out.print(Modifier.toString(constructors.getModifiers()) + );
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
          }

    這里要進(jìn)行異常捕獲,因?yàn)榭赡懿淮嬖趯?yīng)的構(gòu)造方法,打印結(jié)果如下:

    Java反射技術(shù)怎么用

    如果我們想獲取有兩個(gè)參數(shù)分別為int和String類型的構(gòu)造方法,代碼如下:

      Class[] p = {int.class,String.class};
      try {
           constructors = c4.getDeclaredConstructor(p);
           System.out.print(Modifier.toString(constructors.getModifiers()) + "參數(shù):");
           Class[] parametertypes = constructors.getParameterTypes();
           for (int j = 0; j < parametertypes.length; j++) {
                System.out.print(parametertypes[j].getName() + " ");
              }
           } catch (NoSuchMethodException e) {
                e.printStackTrace();
         }

    這里我們同樣打印出構(gòu)造方法的參數(shù):

    Java反射技術(shù)怎么用

    調(diào)用構(gòu)造方法

    從這里開始慢慢到了關(guān)鍵的一步,得到類的實(shí)例,我們主要借助于newInstance方法,為了方便演示我們將測試類的兩個(gè)構(gòu)造方法打印出來.

       public Test(int age, String name) {
            this.age = age;
            this.name = name;
            System.out.println("hello" + name + "i am" + age);
        }
        private Test(String name) {
            this.name = name;
            System.out.println("My Name is" +
                    name);
        }

    我們先來調(diào)用public的方法,如下所示:

     Class[] p = {int.class,String.class};
     constructors = c4.getDeclaredConstructor(p);
     constructors.newInstance(24,"HuangLinqing");

    運(yùn)行打印結(jié)果如下:

    Java反射技術(shù)怎么用

    那么調(diào)用私有構(gòu)造方法呢,和上面一樣,只是我們要設(shè)置constructors.setAccessible(true);代碼如下:

      Class[] p = {String.class};
      constructors = c4.getDeclaredConstructor(p);
      constructors.setAccessible(true);
      constructors.newInstance("HuangLinqing");

    打印結(jié)果如下:

    Java反射技術(shù)怎么用

    調(diào)用類的私有方法

    如何調(diào)用類中的私有方法呢,我們先在測試類中編寫一個(gè)測試的私有方法 如下:

      private void welcome(String tips){
            System.out.println(tips);
        }

    我們知道如果我們要正常的調(diào)用類的方法都是通過類.方法調(diào)用,所以我們調(diào)用私有方法也需要得到類的實(shí)例,而我們上面newInstace已經(jīng)得到了類的實(shí)例,這樣就好辦了。

       Class[] p4 = {String.class};
       Method method = c4.getDeclaredMethod("welcome",p4);
       method.setAccessible(true);

    我們首先通過 getDeclaredMethod方法獲取到這個(gè)私有方法,第一個(gè)參數(shù)是方法名,第二個(gè)參數(shù)是參數(shù)類型

    然后通過invoke方法執(zhí)行,invoke需要兩個(gè)參數(shù)一個(gè)是類的實(shí)例,一個(gè)是方法參數(shù)。

     Class[] p4 = {String.class};
         Method method = c4.getDeclaredMethod("welcome",p4);
         method.setAccessible(true);
         Object arg1s[] = {"歡迎關(guān)注代碼男人技術(shù)公眾號"};
         method.invoke(test,arg1s);

    test類的實(shí)例當(dāng)不能new 獲取的時(shí)候我們也可以通過反射獲取,就是上面的newInstance方法。

    打印結(jié)果如下:

    Java反射技術(shù)怎么用

    獲取類的私有字段并修改值

    看到這里你可能會(huì)說,有了set方法,什么私有不私有,test.set不就可以了,但是這里要注意我們是沒有辦法得到這個(gè)類的實(shí)例的,要不然都可以得到實(shí)例就沒有反射一說了。我們在通過反射得到類的實(shí)例之后先獲取字段:

    Field field = c4.getDeclaredField("name");
    field.setAccessible(true);
    field.set(o,"代碼男人");

    是我們上面通過反射構(gòu)造方法獲取的實(shí)例, 打印field.get(o).toString()的值如下:

    Java反射技術(shù)怎么用

    不過要注意的是我們修改了name的值只對當(dāng)前的實(shí)例對象有效。

    Java的基本反射語法就是這樣了,歡迎加入技術(shù)群一起探討!

    最后反射封裝類如下:

    package jnidemo.hlq.com.hookdemo;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    /**
     * @author Huanglinqing
     * @date 2019/4/28
     */
    public class Reflex {
        /**
         * 獲取無參構(gòu)造函數(shù)
         * @param className
         * @return
         */
        public static Object createObject(String className) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 獲取無參構(gòu)造方法
         * @param clazz
         * @return
         */
        public static Object createObject(Class clazz) {
            Class[] pareTyple = new Class[]{};
            Object[] pareVaules = new Object[]{};
            return createObject(clazz, pareTyple, pareVaules);
        }
        /**
         * 獲取一個(gè)參數(shù)的構(gòu)造函數(shù)  已知className
         *
         * @param className
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object createObject(String className, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 獲取單個(gè)參數(shù)的構(gòu)造方法 已知類
         *
         * @param clazz
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
            return createObject(clazz, pareTyples, pareVaules);
        }
        /**
         * 獲取多個(gè)參數(shù)的構(gòu)造方法 已知className
         * @param className
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 獲取構(gòu)造方法
         *
         * @param clazz
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
            try {
                Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
                ctor.setAccessible(true);
                return ctor.newInstance(pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 獲取多個(gè)參數(shù)的方法
         * @param obj
         * @param methodName
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
            if (obj == null) {
                return null;
            }
            try {
                //調(diào)用一個(gè)private方法 //在指定類中獲取指定的方法
                Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
                method.setAccessible(true);
                return method.invoke(obj, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 獲取一個(gè)參數(shù)的方法
         * @param obj
         * @param methodName
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = {pareTyple};
            Object[] pareVaules = {pareVaule};
            return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
        }
        /**
         * 獲取無參方法
         * @param obj
         * @param methodName
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
            return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
        }
        /**
         * 無參靜態(tài)方法
         * @param className
         * @param method_name
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
            return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
        }
        /**
         * 獲取一個(gè)參數(shù)的靜態(tài)方法
         * @param className
         * @param method_name
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
            return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
        }
        /**
         * 獲取多個(gè)參數(shù)的靜態(tài)方法
         * @param className
         * @param method_name
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
            try {
                Class obj_class = Class.forName(className);
                return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 無參靜態(tài)方法
         * @param method_name
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
            return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
        }
        /**
         * 一個(gè)參數(shù)靜態(tài)方法
         * @param clazz
         * @param method_name
         * @param classType
         * @param pareVaule
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
            Class[] classTypes = new Class[]{classType};
            Object[] pareVaules = new Object[]{pareVaule};
            return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
        }
        /**
         * 多個(gè)參數(shù)的靜態(tài)方法
         * @param clazz
         * @param method_name
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
            try {
                Method method = clazz.getDeclaredMethod(method_name, pareTyples);
                method.setAccessible(true);
                return method.invoke(null, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        public static Object getFieldObject(String className, Object obj, String filedName) {
            try {
                Class obj_class = Class.forName(className);
                return getFieldObject(obj_class, obj, filedName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
        public static Object getFieldObject(Class clazz, Object obj, String filedName) {
            try {
                Field field = clazz.getDeclaredField(filedName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
            try {
                Field field = clazz.getDeclaredField(filedName);
                field.setAccessible(true);
                field.set(obj, filedVaule);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
            try {
                Class obj_class = Class.forName(className);
                setFieldObject(obj_class, obj, filedName, filedVaule);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        public static Object getStaticFieldObject(String className, String filedName) {
            return getFieldObject(className, null, filedName);
        }
        public static Object getStaticFieldObject(Class clazz, String filedName) {
            return getFieldObject(clazz, null, filedName);
        }
        public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
            setFieldObject(classname, null, filedName, filedVaule);
        }
        public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
            setFieldObject(clazz, null, filedName, filedVaule);
        }
    }

    以上是“Java反射技術(shù)怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI