博客
关于我
Java反射机制整理
阅读量:385 次
发布时间:2019-03-05

本文共 9796 字,大约阅读时间需要 32 分钟。

Java反射机制详解

反射是Java语言中的一个强大特性,允许开发者在运行时对类、对象、字段、方法等进行动态操作。它不仅可以用来检查对象的类型,还能动态加载类、创建对象、访问属性和方法等。反射机制在Java应用开发中具有重要的功能,广泛应用于代码执行、测试、调试等多个方面。本文将详细介绍Java反射机制的核心类及其常用方法,并通过实际案例展示反射的应用场景。


Java反射机制概述

反射机制的核心在于Class类,它是Java中表示类和接口的实体。在反射中,Class类提供了丰富的方法,用于动态操作类、字段、方法等。反射的主要功能包括:

  • 动态加载类
  • 动态创建对象
  • 动态访问属性和方法

  • Java反射的核心类

    在Java反射中,Class类是最核心的类,其余如Field、Method、Constructor等都属于Class类的子类。以下是这些核心类的主要功能:

    1. Class类

    Class类用于表示类和接口,在反射中可以通过Class类完成以下操作:

    • 动态加载类:通过forName(String className)方法加载指定类名的类。
    • 获得类的信息:如类名、加载器、父类、接口等,通过getName()getClasses()getSuperclass()等方法获取。
    • 反射方法和字段:通过getMethod()getDeclaredMethod()等方法获取方法,通过getField()getDeclaredField()等方法获取字段。

    2. Field类

    Field类用于反射类的字段(即成员变量)。主要方法包括:

    • 获取字段值:get(Object obj)getDeclaredField(String name)
    • 设置字段值:set(Object obj, Object value)
    • 比较字段:equals(Object obj)

    3. Method类

    Method类用于反射类的方法,主要方法包括:

    • 调用方法:invoke(Object obj, Object... args)
    • 获取方法参数:getMethod(String name, Class<?>... parameterTypes)getDeclaredMethod(String name, Class<?>... parameterTypes)

    4. Constructor类

    Constructor类用于反射类的构造方法,主要方法包括:

    • 通过反射创建对象:newInstance(Object... initargs)
    • 获取特定构造方法:getDeclaredConstructor(Class<?>... parameterTypes)getConstructor(Class<?>... parameterTypes)

    Class类的常用方法

    Class类是反射的核心类,其方法种类繁多,主要包括以下几类:

    1. 获取类信息的方法

    • getName():返回类的全名。
    • getClasses():返回当前类的所有公开类和接口。
    • getDeclaredClasses():返回当前类的所有类和接口(包括非公开的)。

    2. 反射方法的方法

    • getMethod(String name, Class<?>... parameterTypes):获取某个公开方法。
    • getMethods():获取当前类的所有公开方法。
    • getDeclaredMethod(String name, Class<?>... parameterTypes):获取某个方法(包括非公开的)。
    • getDeclaredMethods():获取当前类的所有方法(包括非公开的)。

    3. 反射字段的方法

    • getField(String name):获取某个公开字段。
    • getFields():获取当前类的所有公开字段。
    • getDeclaredField(String name):获取某个字段(包括非公开的)。
    • getDeclaredFields():获取当前类的所有字段(包括非公开的)。

    4. 反射注解的方法

    • getAnnotation(Class<? extends Annotation> annotationClass):获取某个注解。
    • getAnnotations():获取当前类的所有注解。
    • getDeclaredAnnotation(Class<? extends Annotation> annotationClass):获取某个注解(包括非公开的)。
    • getDeclaredAnnotations():获取当前类的所有注解(包括非公开的)。

    5. 其他重要方法

    • newInstance(Object... initargs):根据参数创建类的实例。
    • getPackage():获取类的包。
    • isAnnotation():判断是否是注解类型。
    • isArray():判断是否是数组类。
    • isEnum():判断是否是枚举类。

    Field类的常用方法

    Field类用于反射字段,其主要方法包括:

    • get(Object obj):获取指定对象的字段值。
    • getDeclaredField(String name):获取指定字段名的字段。
    • set(Object obj, Object value):设置指定对象的字段值。
    • equals(Object obj):判断两个字段是否相等。

    Method类的常用方法

    Method类用于反射方法,其主要方法包括:

    • invoke(Object obj, Object... args):调用指定对象的方法。
    • getMethod(String name, Class<?>... parameterTypes):获取某个方法。
    • getDeclaredMethod(String name, Class<?>... parameterTypes):获取某个方法(包括非公开的)。

    Constructor类的常用方法

    Constructor类用于反射构造方法,其主要方法包括:

    • newInstance(Object... initargs):根据参数创建类实例。
    • getDeclaredConstructor(Class<?>... parameterTypes):获取特定构造方法。
    • getConstructor(Class<?>... parameterTypes):获取公开的构造方法。

    Java反射的实际应用示例

    为了更好地理解反射机制,我们可以通过一个具体的例子——Book类,展示反射的基本操作。以下是Book类的代码:

    public class Book {    private final static String TAG = "BookTag";    private String name;    private String author;    public Book() {    }    private Book(String name, String author) {        this.name = name;        this.author = author;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getAuthor() {        return author;    }    public void setAuthor(String author) {        this.author = author;    }    private String declaredMethod(int index) {        String string = null;        switch (index) {            case 0:                string = "I am declaredMethod 1 !";                break;            case 1:                string = "I am declaredMethod 2 !";                break;            default:                string = "I am declaredMethod 1 !";        }        return string;    }}

    接下来,我们可以通过反射创建Book对象,并对其进行操作。以下是ReflectClass类的代码:

    public class ReflectClass {    private final static String TAG = "peter.log.ReflectClass";    // 创建对象    public static void reflectNewInstance() {        try {            Class classBook = Class.forName("com.android.peter.reflectdemo.Book");            Object objectBook = classBook.newInstance();            Book book = (Book) objectBook;            book.setName("Android进阶之光");            book.setAuthor("刘望舒");            Log.d(TAG, "reflectNewInstance book = " + book.toString());        } catch (Exception ex) {            ex.printStackTrace();        }    }    // 反射私有的构造方法    public static void reflectPrivateConstructor() {        try {            Class classBook = Class.forName("com.android.peter.reflectdemo.Book");            Constructor declaredConstructorBook = classBook.getDeclaredConstructor(String.class, String.class);            declaredConstructorBook.setAccessible(true);            Object objectBook = declaredConstructorBook.newInstance("Android开发艺术探索", "任玉刚");            Book book = (Book) objectBook;            Log.d(TAG, "reflectPrivateConstructor book = " + book.toString());        } catch (Exception ex) {            ex.printStackTrace();        }    }    // 反射私有属性    public static void reflectPrivateField() {        try {            Class classBook = Class.forName("com.android.peter.reflectdemo.Book");            Object objectBook = classBook.newInstance();            Field fieldTag = classBook.getDeclaredField("TAG");            fieldTag.setAccessible(true);            String tag = (String) fieldTag.get(objectBook);            Log.d(TAG, "reflectPrivateField tag = " + tag);        } catch (Exception ex) {            ex.printStackTrace();        }    }    // 反射私有方法    public static void reflectPrivateMethod() {        try {            Class classBook = Class.forName("com.android.peter.reflectdemo.Book");            Method methodBook = classBook.getDeclaredMethod("declaredMethod", int.class);            methodBook.setAccessible(true);            Object objectBook = classBook.newInstance();            String string = (String) methodBook.invoke(objectBook, 0);            Log.d(TAG, "reflectPrivateMethod string = " + string);        } catch (Exception ex) {            ex.printStackTrace();        }    }    // 获得系统Zenmode值    public static int getZenMode() {        int zenMode = -1;        try {            Class cServiceManager = Class.forName("android.os.ServiceManager");            Method mGetService = cServiceManager.getMethod("getService", String.class);            Object oNotificationManagerService = mGetService.invoke(null, Context.NOTIFICATION_SERVICE);            Class cINotificationManagerStub = Class.forName("android.app.INotificationManager$Stub");            Method mAsInterface = cINotificationManagerStub.getMethod("asInterface", Binder.class);            Object oINotificationManager = mAsInterface.invoke(null, oNotificationManagerService);            Method mGetZenMode = cINotificationManagerStub.getMethod("getZenMode");            zenMode = (Integer) mGetZenMode.invoke(oINotificationManager);        } catch (Exception ex) {            ex.printStackTrace();        }        return zenMode;    }    // 关闭手机    public static void shutDown() {        try {            Class cServiceManager = Class.forName("android.os.ServiceManager");            Method mGetService = cServiceManager.getMethod("getService", String.class);            Object oPowerManagerService = mGetService.invoke(null, Context.POWER_SERVICE);            Class cIPowerManagerStub = Class.forName("android.os.IPowerManager$Stub");            Method mShutdown = cIPowerManagerStub.getMethod("shutdown", boolean.class, String.class, boolean.class);            Method mAsInterface = cIPowerManagerStub.getMethod("asInterface", Binder.class);            Object oIPowerManager = mAsInterface.invoke(null, oPowerManagerService);            mShutdown.invoke(oIPowerManager, true, null, false);        } catch (Exception ex) {            ex.printStackTrace();        }    }    public static void shutdownOrReboot(final boolean shutdown, final boolean confirm) {        try {            Class ServiceManager = Class.forName("android.os.ServiceManager");            // 获得ServiceManager的getService方法            Method getService = ServiceManager.getMethod("getService", String.class);            // 调用getService获取RemoteService            Object oRemoteService = getService.invoke(null, Context.POWER_SERVICE);            // 获得IPowerManager.Stub类            Class cStub = Class.forName("android.os.IPowerManager$Stub");            // 获得asInterface方法            Method asInterface = cStub.getMethod("asInterface", Binder.class);            // 调用asInterface方法获取IPowerManager对象            Object oIPowerManager = asInterface.invoke(null, oRemoteService);            if (shutdown) {                // 获得shutdown()方法                Method shutdownMethod = oIPowerManager.getClass().getMethod("shutdown", boolean.class, String.class, boolean.class);                // 调用shutdown()方法                shutdownMethod.invoke(oIPowerManager, confirm, null, false);            } else {                // 获得reboot()方法                Method rebootMethod = oIPowerManager.getClass().getMethod("reboot", boolean.class, String.class, boolean.class);                // 调用reboot()方法                rebootMethod.invoke(oIPowerManager, confirm, null, false);            }        } catch (Exception e) {            e.printStackTrace();        }    }}// 调用相应反射逻辑方法try {    ReflectClass.reflectNewInstance();    ReflectClass.reflectPrivateConstructor();    ReflectClass.reflectPrivateField();    ReflectClass.reflectPrivateMethod();} catch (Exception ex) {    ex.printStackTrace();}Log.d(TAG, " zenmode = " + ReflectClass.getZenMode());

    反射的注意事项

  • 权限问题:在反射调用某些系统方法时,可能会因为权限问题导致SecurityException。如反射调用PowerManager.shutdown()方法时,需要确保应用有相应的权限(如REBOOT)。
  • 性能问题:反射操作比直接调用方法稍慢,特别是在频繁调用反射方法时,可能会影响应用性能。
  • 代码可读性:反射代码虽然灵活,但代码不够直观,影响可读性。建议在使用反射时谨慎操作,并根据实际需求选择反射或直接调用方法。

  • 总结

    反射机制为Java程序提供了强大的动态操作能力。在实际开发中,反射可以用来解决无法通过接口或子类继承关系进行操作的问题。通过ClassFieldMethodConstructor等类的反射方法,可以实现对类、对象、字段、方法等的动态操作。

    如需更深入了解反射机制,可以参考Java官方文档或相关开源资料。

    转载地址:http://dbqwz.baihongyu.com/

    你可能感兴趣的文章
    mysql 递归查找父节点_MySQL递归查询树状表的子节点、父节点具体实现
    查看>>
    mysql 通过查看mysql 配置参数、状态来优化你的mysql
    查看>>
    mysql 里对root及普通用户赋权及更改密码的一些命令
    查看>>
    Mysql 重置自增列的开始序号
    查看>>
    mysql 锁机制 mvcc_Mysql性能优化-事务、锁和MVCC
    查看>>
    MySQL 错误
    查看>>
    mysql 随机数 rand使用
    查看>>
    MySQL 面试题汇总
    查看>>
    MySQL 面试,必须掌握的 8 大核心点
    查看>>
    MySQL 高可用性之keepalived+mysql双主
    查看>>
    MySQL 高性能优化规范建议
    查看>>
    mysql 默认事务隔离级别下锁分析
    查看>>
    Mysql--逻辑架构
    查看>>
    MySql-2019-4-21-复习
    查看>>
    mysql-5.6.17-win32免安装版配置
    查看>>
    mysql-5.7.18安装
    查看>>
    MySQL-Buffer的应用
    查看>>
    mysql-cluster 安装篇(1)---简介
    查看>>
    mysql-connector-java.jar乱码,最新版mysql-connector-java-8.0.15.jar,如何愉快的进行JDBC操作...
    查看>>
    mysql-connector-java各种版本下载地址
    查看>>