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

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

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/

    你可能感兴趣的文章
    MuseTalk如何生成高质量视频(使用技巧)
    查看>>
    mutiplemap 总结
    查看>>
    MySQL DELETE 表别名问题
    查看>>
    MySQL Error Handling in Stored Procedures---转载
    查看>>
    MVC 区域功能
    查看>>
    MySQL FEDERATED 提示
    查看>>
    mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
    查看>>
    Mysql group by
    查看>>
    MySQL I 有福啦,窗口函数大大提高了取数的效率!
    查看>>
    mysql id自动增长 初始值 Mysql重置auto_increment初始值
    查看>>
    MySQL in 太多过慢的 3 种解决方案
    查看>>
    MySQL InnoDB 三大文件日志,看完秒懂
    查看>>
    Mysql InnoDB 数据更新导致锁表
    查看>>
    Mysql Innodb 锁机制
    查看>>
    MySQL InnoDB中意向锁的作用及原理探
    查看>>
    MySQL InnoDB事务隔离级别与锁机制深入解析
    查看>>
    Mysql InnoDB存储引擎 —— 数据页
    查看>>
    Mysql InnoDB存储引擎中的checkpoint技术
    查看>>
    Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
    查看>>
    MySQL InnoDB引擎的锁机制详解
    查看>>