Rumah  >  Artikel  >  Java  >  Cara menggunakan refleksi Java dan analisis contoh

Cara menggunakan refleksi Java dan analisis contoh

WBOY
WBOYke hadapan
2023-05-06 16:31:08539semak imbas

    Refleksi

    Definisi refleksi

    Sesuatu objek boleh mendapatkan kelasnya melalui refleksi, dan kelas boleh memperoleh semua kaedah (termasuk Persendirian) Anda boleh mengendalikan fail bytecode melalui mekanisme pantulan dalam bahasa java, dan anda boleh membaca dan mengubah suai fail bytecode

    Aplikasi asas pantulan

    1 Dapatkan objek kelas

    a . forName() kaedah

    hanya perlu mengetahui nama kelas dan kod instance akan digunakan semasa memuatkan JDBC

    public class test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Class name = Class.forName("java.lang.Runtime");
            System.out.println(name);
        }
    }

    Cara menggunakan refleksi Java dan analisis contoh

    b

    Gunakan .class untuk mendapatkan objek

    public class test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> name = Runtime.class;
            System.out.println(name);
        }
    }
    c kaedah getClass()

    getClass untuk mendapatkan objek bytecode, anda mesti menentukan kelas tertentu dan kemudian mencipta objek

    public class test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            Runtime rt = Runtime.getRuntime();
            Class<?> name = rt.getClass();
            System.out.println(name);
        }
    }
    d. kaedah getSystemClassLoader().loadClass()

    Kaedah ini serupa dengan forName, selagi terdapat nama kelas, tetapi perbezaannya ialah JVM statik forName akan memuatkan kelas dan Jalankan kod dalam static()

    public class getSystemClassLoader {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> name = ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime");
            System.out.println(name);
        }
    }

    2 Dapatkan kaedah kelas

    a. termasuk kaedah awam, dilindungi, persendirian dan Lalai, tetapi tidak termasuk kaedah yang diwarisi
    import java.lang.reflect.Method;
    
    public class getDeclaredMethods {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> name = Class.forName("java.lang.Runtime");
            System.out.println(name);
            Method[] m = name.getDeclaredMethods();
            for(Method x:m)
                System.out.println(x);
        }
    }

    Cara menggunakan refleksi Java dan analisis contohb getDeclaredMethod

    mendapat kaedah khusus, parameter pertama ialah nama kaedah, parameter kedua Parameter ialah objek kelas yang sepadan dengan parameter kaedah Contohnya, parameter kaedah exec Runtime di sini ialah String, jadi parameter kedua di sini ialah String.class
    import java.lang.reflect.Method;
    
    public class getDeclaredMethod {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
            Class<?> name = Class.forName("java.lang.Runtime");
            Method m = name.getDeclaredMethod("exec",String.class);
            System.out.println(m);
        }
    }
    c. getMethods

    mengembalikan Semua kaedah awam kelas, termasuk kaedah awam kelas yang diwarisi
    d getMethod

    parameter adalah sama dengan getDeclaredMethod
    3. Dapatkan pembolehubah ahli

    Dengan cara yang sama, kaedah Kaedah

    a getDeclaredFields

    dapatkan semua tatasusunan pembolehubah ahli kelas, tetapi lakukan. tidak termasuk kelas induk

    b. getDeclaredField(String name )

    Dapatkan khusus, parameter ialah nama kaedah yang dikehendaki

    c
    Begitu juga, anda hanya boleh mendapatkan awam, tetapi masukkan kelas induk

    d getField(Nama rentetan)
    Begitu juga, parameter ialah nama kaedah yang diingini

    4. Dapatkan Pembina Pembina

    Pembina>[] getConstructors(): hanya mengembalikan pembina awam

    Constructor>[] getDeclaredConstructors(): mengembalikan semua pembina

    Pembina getConstructor (Kelas >... parameterTypes): Padan dengan pembina awam

    Constructor getDeclaredConstructor (Kelas >... parameterTypes): Padanan dan parameter Parameter pembina yang sepadan dengan jenis padanan

    ialah objek kelas jenis parameter kaedah, serupa dengan Kaedah, seperti

    5. Reflection mencipta objek kelas

    newInstanceString.class

    boleh menjana objek instantiated melalui refleksi Secara amnya, kami menggunakan kaedah

    objek Kelas untuk mencipta objek kelas

    . Iaitu: anda hanya perlu mencipta kaedah newInstance dalam objek kelas yang diperoleh melalui kaedah forname
    Class c = Class.forName("com.reflect.MethodTest"); // 创建Class对象
    Object m1 =  c.newInstance(); // 创建类对象

    kaedah invokenewInstance()

    kaedah invoke terletak dalam java.lang.reflect .Kaedah kelas dan digunakan untuk melaksanakan tertentu Kaedah sasaran objek biasanya dipanggil bersama-sama dengan kaedah getMethod.

    Penggunaan:
    public Object invoke(Object obj, Object... args)
    Parameter pertama ialah contoh kelas, parameter kedua ialah parameter dalam fungsi yang sepadan

    obj: objek dari mana kaedah asas dipanggil, Mesti objek instantiated

    args: digunakan untuk penyeruan kaedah Ia adalah tatasusunan objek Parameter mungkin berbilang

    , tetapi perlu diperhatikan bahawa parameter pertama. kaedah invoke tidak Ia tidak tetap:

    Jika memanggil kaedah ini adalah kaedah biasa, parameter pertama ialah objek kelas; >Jika memanggil kaedah ini ialah Kaedah statik, parameter pertama ialah kelas; adakah dalam istilah mudah

      Method.invoke (objek kelas atau kelas)
    • Mula-mula dapatkan Class forName, kemudian dapatkan objek kelas dengan newInstance, kemudian dapatkan kaedah dengan getMethod, dan kemudian panggil
    • Contoh rce Runtime (penembusan sekatan akses)

      Terdapat kaedah exec dalam kelas Runtime, yang boleh melaksanakan arahan
    • import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;
      
      public class Invoke {
          public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
              Class c = Class.forName("Invoke");
              Object o = c.newInstance();
              Method m = c.getMethod("test");
              m.invoke(o);
          }
          public void test(){
              System.out.println("测试成功");
          }
      }
    tetapi ralat ditemui

    Cara menggunakan refleksi Java dan analisis contoh

    Sebab masalah ini:

    Kelas yang digunakan tidak mempunyai pembina tanpa parameter

    Pembina kelas yang digunakan adalah peribadi

    Kemudian penyelesaiannya ialah

    , gunakan ini untuk memecahkan sekatan akses

    Java.lang.reflect.AccessibleObject类是Field,Method和Constructor类对象的基类,可以提供将反射对象标记为使用它抑制摸人Java访问控制检查的功能,同时上述的反射类中的Field,Method和Constructor继承自AccessibleObject。所以我们在这些类方法基础上调用setAccessible()方法,既可对这些私有字段进行操作

    简单来说,私有的属性、方法、构造方法,可以通过这个去突破限制,xxx.setAccessible(true) 可以看到Runtime的构造方法是private的

    Cara menggunakan refleksi Java dan analisis contoh

    那么这里我们就可以这么去突破限制 先获取构造方法,然后setAccessible获取访问权限 然后再最后invoke里面,第一个参数写成con.newInstance()

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Exec {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
            Class c = Class.forName("java.lang.Runtime");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Method m = c.getMethod("exec",String.class);
            m.invoke(con.newInstance(),"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
        }
    }

    Cara menggunakan refleksi Java dan analisis contoh

    这里有一个疑问,如果把con.newInstance单独提取出来,他打开计算器不会显示出来,但是后台的确是启动了,不知道啥原因

    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Exec {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
            Class c = Class.forName("java.lang.Runtime");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object o = con.newInstance();
            Method m = c.getMethod("exec",String.class);
            m.invoke(o,"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
        }
    }

    后记

    反射中常用的几个重要方法:

    • 获取类的⽅法: forName

    • 实例化类对象的⽅法: newInstance

    • 获取函数的⽅法: getMethod

    • 执⾏函数的⽅法: invoke

    • 限制突破方法:setAccessible

    Atas ialah kandungan terperinci Cara menggunakan refleksi Java dan analisis contoh. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam