Rumah Java javaTutorial Java反射机制详解

Java反射机制详解

Dec 12, 2016 am 11:45 AM
mekanisme refleksi java

概要:

Java反射机制详解

1反射机制是什么

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2反射机制能做什么

反射机制主要提供了以下功能: 

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;

在运行时调用任意一个对象的方法;

生成动态代理。

3反射机制的相关API

通过一个对象获得完整的包名和类名

Java | 复制

package net.xsoftlab.baike;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        TestReflect testReflect = new TestReflect();
        System.out.println(testReflect.getClass().getName());
        // 结果 net.xsoftlab.baike.TestReflect
    }
}
Salin selepas log masuk

实例化Class类对象

Java | 复制

package net.xsoftlab.baike;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> class1 = null;
        Class<?> class2 = null;
        Class<?> class3 = null;
        // 一般采用这种形式
        class1 = Class.forName("net.xsoftlab.baike.TestReflect");
        class2 = new TestReflect().getClass();
        class3 = TestReflect.class;
        System.out.println("类名称   " + class1.getName());
        System.out.println("类名称   " + class2.getName());
        System.out.println("类名称   " + class3.getName());
    }
}
Salin selepas log masuk

获取一个对象的父类与实现的接口

Java | 复制

package net.xsoftlab.baike;
import java.io.Serializable;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        // 取得父类
        Class<?> parentClass = clazz.getSuperclass();
        System.out.println("clazz的父类为:" + parentClass.getName());
        // clazz的父类为: java.lang.Object
        // 获取所有的接口
        Class<?> intes[] = clazz.getInterfaces();
        System.out.println("clazz实现的接口有:");
        for (int i = 0; i < intes.length; i++) {
            System.out.println((i + 1) + ":" + intes[i].getName());
        }
        // clazz实现的接口有:
        // 1:java.io.Serializable
    }
}
Salin selepas log masuk

获取某个类中的全部构造函数 - 详见下例

通过反射机制实例化一个类的对象

Java | 复制

package net.xsoftlab.baike;
import java.lang.reflect.Constructor;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> class1 = null;
        class1 = Class.forName("net.xsoftlab.baike.User");
        // 第一种方法,实例化默认构造方法,调用set赋值
        User user = (User) class1.newInstance();
        user.setAge(20);
        user.setName("Rollen");
        System.out.println(user);
        // 结果 User [age=20, name=Rollen]
        // 第二种方法 取得全部的构造函数 使用构造函数赋值
        Constructor<?> cons[] = class1.getConstructors();
        // 查看每个构造方法需要的参数
        for (int i = 0; i < cons.length; i++) {
            Class<?> clazzs[] = cons[i].getParameterTypes();
            System.out.print("cons[" + i + "] (");
            for (int j = 0; j < clazzs.length; j++) {
                if (j == clazzs.length - 1)
                    System.out.print(clazzs[j].getName());
                else
                    System.out.print(clazzs[j].getName() + ",");
            }
            System.out.println(")");
        }
        // 结果
        // cons[0] (java.lang.String)
        // cons[1] (int,java.lang.String)
        // cons[2] ()
        user = (User) cons[0].newInstance("Rollen");
        System.out.println(user);
        // 结果 User [age=0, name=Rollen]
        user = (User) cons[1].newInstance(20, "Rollen");
        System.out.println(user);
        // 结果 User [age=20, name=Rollen]
    }
}
class User {
    private int age;
    private String name;
    public User() {
        super();
    }
    public User(String name) {
        super();
        this.name = name;
    }
    public User(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}
Salin selepas log masuk

获取某个类的全部属性

Java | 复制

package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        System.out.println("===============本类属性===============");
        // 取得本类的全部属性
        Field[] field = clazz.getDeclaredFields();
        for (int i = 0; i < field.length; i++) {
            // 权限修饰符
            int mo = field[i].getModifiers();
            String priv = Modifier.toString(mo);
            // 属性类型
            Class<?> type = field[i].getType();
            System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
        }
         
        System.out.println("==========实现的接口或者父类的属性==========");
        // 取得实现的接口或者父类的属性
        Field[] filed1 = clazz.getFields();
        for (int j = 0; j < filed1.length; j++) {
            // 权限修饰符
            int mo = filed1[j].getModifiers();
            String priv = Modifier.toString(mo);
            // 属性类型
            Class<?> type = filed1[j].getType();
            System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
        }
    }
}
Salin selepas log masuk

获取某个类的全部方法

Java | 复制

package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Method method[] = clazz.getMethods();
        for (int i = 0; i < method.length; ++i) {
            Class<?> returnType = method[i].getReturnType();
            Class<?> para[] = method[i].getParameterTypes();
            int temp = method[i].getModifiers();
            System.out.print(Modifier.toString(temp) + " ");
            System.out.print(returnType.getName() + "  ");
            System.out.print(method[i].getName() + " ");
            System.out.print("(");
            for (int j = 0; j < para.length; ++j) {
                System.out.print(para[j].getName() + " " + "arg" + j);
                if (j < para.length - 1) {
                    System.out.print(",");
                }
            }
            Class<?> exce[] = method[i].getExceptionTypes();
            if (exce.length > 0) {
                System.out.print(") throws ");
                for (int k = 0; k < exce.length; ++k) {
                    System.out.print(exce[k].getName() + " ");
                    if (k < exce.length - 1) {
                        System.out.print(",");
                    }
                }
            } else {
                System.out.print(")");
            }
            System.out.println();
        }
    }
}
Salin selepas log masuk

通过反射机制调用某个类的方法

Java | 复制

package net.xsoftlab.baike;
import java.lang.reflect.Method;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        // 调用TestReflect类中的reflect1方法
        Method method = clazz.getMethod("reflect1");
        method.invoke(clazz.newInstance());
        // Java 反射机制 - 调用某个类的方法1.
        // 调用TestReflect的reflect2方法
        method = clazz.getMethod("reflect2", int.class, String.class);
        method.invoke(clazz.newInstance(), 20, "张三");
        // Java 反射机制 - 调用某个类的方法2.
        // age -> 20. name -> 张三
    }
    public void reflect1() {
        System.out.println("Java 反射机制 - 调用某个类的方法1.");
    }
    public void reflect2(int age, String name) {
        System.out.println("Java 反射机制 - 调用某个类的方法2.");
        System.out.println("age -> " + age + ". name -> " + name);
    }
}
Salin selepas log masuk

通过反射机制操作某个类的属性

Java | 复制

package net.xsoftlab.baike;
import java.lang.reflect.Field;
public class TestReflect {
    private String proprety = null;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Object obj = clazz.newInstance();
        // 可以直接对 private 的属性赋值
        Field field = clazz.getDeclaredField("proprety");
        field.setAccessible(true);
        field.set(obj, "Java反射机制");
        System.out.println(field.get(obj));
    }
}
Salin selepas log masuk

反射机制的动态代理

Java | 复制

// 获取类加载器的方法
TestReflect testReflect = new TestReflect();
        System.out.println("类加载器  " + testReflect.getClass().getClassLoader().getClass().getName());
package net.xsoftlab.baike;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//定义项目接口
interface Subject {
    public String say(String name, int age);
}
// 定义真实项目
class RealSubject implements Subject {
    public String say(String name, int age) {
        return name + "  " + age;
    }
}
class MyInvocationHandler implements InvocationHandler {
    private Object obj = null;
    public Object bind(Object obj) {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object temp = method.invoke(this.obj, args);
        return temp;
    }
}
/**
 * 在java中有三种类类加载器。
 * 
 * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
 * 
 * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
 * 
 * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
 * 
 * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
 * 
 * @author xsoftlab.net
 * 
 */
public class TestReflect {
    public static void main(String[] args) throws Exception {
        MyInvocationHandler demo = new MyInvocationHandler();
        Subject sub = (Subject) demo.bind(new RealSubject());
        String info = sub.say("Rollen", 20);
        System.out.println(info);
    }
}
Salin selepas log masuk

4反射机制的应用实例

在泛型为Integer的ArrayList中存放一个String类型的对象。

Java | 复制

package net.xsoftlab.baike;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list = new ArrayList<Integer>();
        Method method = list.getClass().getMethod("add", Object.class);
        method.invoke(list, "Java反射机制实例。");
        System.out.println(list.get(0));
    }
}
Salin selepas log masuk

通过反射取得并修改数组的信息

Java | 复制

package net.xsoftlab.baike;
import java.lang.reflect.Array;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        int[] temp = { 1, 2, 3, 4, 5 };
        Class<?> demo = temp.getClass().getComponentType();
        System.out.println("数组类型: " + demo.getName());
        System.out.println("数组长度  " + Array.getLength(temp));
        System.out.println("数组的第一个元素: " + Array.get(temp, 0));
        Array.set(temp, 0, 100);
        System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
    }
}
Salin selepas log masuk

通过反射机制修改数组的大小

Java | 复制

package net.xsoftlab.baike;
import java.lang.reflect.Array;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        int[] newTemp = (int[]) arrayInc(temp, 15);
        print(newTemp);
        String[] atr = { "a", "b", "c" };
        String[] str1 = (String[]) arrayInc(atr, 8);
        print(str1);
    }
    // 修改数组大小
    public static Object arrayInc(Object obj, int len) {
        Class<?> arr = obj.getClass().getComponentType();
        Object newArr = Array.newInstance(arr, len);
        int co = Array.getLength(obj);
        System.arraycopy(obj, 0, newArr, 0, co);
        return newArr;
    }
    // 打印
    public static void print(Object obj) {
        Class<?> c = obj.getClass();
        if (!c.isArray()) {
            return;
        }
        System.out.println("数组长度为: " + Array.getLength(obj));
        for (int i = 0; i < Array.getLength(obj); i++) {
            System.out.print(Array.get(obj, i) + " ");
        }
        System.out.println();
    }
}
Salin selepas log masuk

将反射机制应用于工厂模式

Java | 复制

package net.xsoftlab.baike;
interface fruit {
    public abstract void eat();
}
class Apple implements fruit {
    public void eat() {
        System.out.println("Apple");
    }
}
class Orange implements fruit {
    public void eat() {
        System.out.println("Orange");
    }
}
class Factory {
    public static fruit getInstance(String ClassName) {
        fruit f = null;
        try {
            f = (fruit) Class.forName(ClassName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }
}
/**
 * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
 * Java 工厂模式可以参考
 * http://baike.xsoftlab.net/view/java-factory-pattern
 * 
 * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
 * 
 * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
 * 
 * java 读取 properties 配置文件 的方法可以参考
 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file
 * 
 * @author xsoftlab.net
 */
public class TestReflect {
    public static void main(String[] args) throws Exception {
        fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");
        if (f != null) {
            f.eat();
        }
    }
}
Salin selepas log masuk


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimana dengan elegan mendapatkan nama pemboleh ubah kelas entiti untuk membina keadaan pertanyaan pangkalan data? Bagaimana dengan elegan mendapatkan nama pemboleh ubah kelas entiti untuk membina keadaan pertanyaan pangkalan data? Apr 19, 2025 pm 11:42 PM

Apabila menggunakan Mybatis-Plus atau Rangka Kerja ORM yang lain untuk operasi pangkalan data, sering diperlukan untuk membina syarat pertanyaan berdasarkan nama atribut kelas entiti. Sekiranya anda secara manual setiap kali ...

Adakah perisian keselamatan syarikat menyebabkan aplikasi gagal dijalankan? Bagaimana cara menyelesaikan masalah dan menyelesaikannya? Adakah perisian keselamatan syarikat menyebabkan aplikasi gagal dijalankan? Bagaimana cara menyelesaikan masalah dan menyelesaikannya? Apr 19, 2025 pm 04:51 PM

Penyelesaian masalah dan penyelesaian kepada perisian keselamatan syarikat yang menyebabkan beberapa aplikasi tidak berfungsi dengan baik. Banyak syarikat akan menggunakan perisian keselamatan untuk memastikan keselamatan rangkaian dalaman. …

Bagaimana untuk memudahkan isu pemetaan medan dalam dok sistem menggunakan mapstruct? Bagaimana untuk memudahkan isu pemetaan medan dalam dok sistem menggunakan mapstruct? Apr 19, 2025 pm 06:21 PM

Pemprosesan pemetaan medan dalam dok sistem sering menemui masalah yang sukar ketika melaksanakan sistem dok: bagaimana untuk memetakan medan antara muka sistem dengan berkesan ...

Bagaimanakah Idea IntelliJ mengenal pasti nombor port projek boot musim bunga tanpa mengeluarkan log? Bagaimanakah Idea IntelliJ mengenal pasti nombor port projek boot musim bunga tanpa mengeluarkan log? Apr 19, 2025 pm 11:45 PM

Mula musim bunga menggunakan versi IntelliJideaultimate ...

Bagaimana cara menukar objek Java dengan selamat ke array? Bagaimana cara menukar objek Java dengan selamat ke array? Apr 19, 2025 pm 11:33 PM

Penukaran objek dan tatasusunan Java: Perbincangan mendalam tentang risiko dan kaedah penukaran jenis cast yang betul Banyak pemula Java akan menemui penukaran objek ke dalam array ...

Apakah perbezaan antara kebocoran memori dalam program Java pada CPU ARM dan X86 Architecture? Apakah perbezaan antara kebocoran memori dalam program Java pada CPU ARM dan X86 Architecture? Apr 19, 2025 pm 11:18 PM

Analisis fenomena kebocoran memori program Java pada CPU seni bina yang berbeza. Artikel ini akan membincangkan kes di mana program Java mempamerkan tingkah laku memori yang berbeza di lengan dan cpus seni bina x86 ...

Bagaimana menggunakan penyelesaian cache Redis untuk merealisasikan keperluan senarai kedudukan produk dengan cekap? Bagaimana menggunakan penyelesaian cache Redis untuk merealisasikan keperluan senarai kedudukan produk dengan cekap? Apr 19, 2025 pm 11:36 PM

Bagaimanakah penyelesaian caching Redis menyedari keperluan senarai kedudukan produk? Semasa proses pembangunan, kita sering perlu menangani keperluan kedudukan, seperti memaparkan ...

Bagaimana cara menukar nama ke nombor untuk melaksanakan penyortiran dalam kumpulan? Bagaimana cara menukar nama ke nombor untuk melaksanakan penyortiran dalam kumpulan? Apr 19, 2025 pm 01:57 PM

Bagaimana cara menukar nama ke nombor untuk melaksanakan penyortiran dalam kumpulan? Apabila menyusun pengguna dalam kumpulan, sering kali perlu menukar nama pengguna ke dalam nombor supaya ia boleh berbeza ...

See all articles