zoukankan      html  css  js  c++  java
  • Java反射机制浅析

    概述:

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


    本文链接:http://blog.csdn.net/lemon_tree12138/article/details/49871515 -- Coding-Naga
                                                                     --转载请注明出处


    反射的基本操作:

    1.获得类名

      通过Java的反射机制我们可以获得一个对象的类。这里的类是类的全名,包含包名。比如:org.demo.reflect.Clazz.

      可能你会问,这个功能有什么用?其实这个功能还是很有用的。比如,我们在打日志的时候,我们就要用到这个功能,来追踪这个日志是在什么地方被打出来的。

    private String getObjectName(Object o) {
            if (o == null) {
                return null;
            }
            
            return o.getClass().getName();
        }

    2.输出一个类的所有对外可见的变量

      注意这里是输出所有对外可见的变量,即变量的修饰符为public.这里使用的是getFields()方法。注意,这里是可以获得其父类中的public变量.

    private void printFields(String clazzName) {
            try {
                Class<?> clazz = Class.forName(clazzName);
                Field[] fields = clazz.getFields();
                for (Field field : fields) {
                    System.out.println(field);
                }
            } catch(ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    3.输出一个类的所有成员变量

      这里是输出一个类的成员变量,不论它是不是对外可见的。就算它是被private修饰,也同样可见。这一点很让人着迷,不是吗?

      这里使用的是getDeclaredFields()。

    private void printDeclaredFields(String clazzName) {
            try {
                Class<?> clazz = Class.forName(clazzName);
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    System.out.println(field);
                }
            } catch(ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    4.输出一个类的所有public方法

      这里与之前的getFields()类似只能对外可见的,即修饰符为public的方法。同样,这里也是可以获得父类的public方法。

    private void printMethods(String clazzName) {
            try {
                Class<?> clazz = Class.forName(clazzName);
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    System.out.println(method);
                }
            } catch(ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    5.输出一个类的所有成员方法

    private void printDeclaredMethods(String clazzName) {
            try {
                Class<?> clazz = Class.forName(clazzName);
                Method[] methods = clazz.getDeclaredMethods();
                for (Method method : methods) {
                    System.out.println(method);
                }
            } catch(ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    6.调用类里面的成员函数

      这里我先假设测试类中有一个sayHello方法,如下:

    public void sayHello(String from) {
        System.out.println("Hello from " + from);
    }

      下面就可以通过getMethod()方法来反射获得这个sayHello方法。getMethod()中第一个参数为方法名,这里即是"sayHello",后面的参数是可变量参数,是可以填写0个或是多个的,值为被反射的方法中的参数类型。这里即是String.class。

      然后再调用invoke()方法,invoke()的第一个参数为被反射的对象,后面是向sayHello()方法中传递的数据。具体过程如下:

    private void callMethod(Object o, String clazzName) {
            try {
                Class<?> clazz = Class.forName(clazzName);
                Method method = clazz.getMethod("sayHello", String.class);
                method.invoke(o, TestReflect.class.getSimpleName());
            } catch(Exception e) {
                e.printStackTrace();
            }
        }

    7.生成一个不能new的对象

      可以看到上面的操作过程,都有一个前提,就是我们已经有了这个对象。那如果我们之前没有这个对象呢?或者说,我们不能显式地获得这个对象。这一点在学习单例模式的时候,就知道其实很好获得,只要把重写默认的构造方法,并把这个构造方法的修饰符修改为private即可。如下:

    private PrivateClass() {
    }

      这里有一点比较特殊,就是这里使用的类或是方法都是私有的。我们不能直接去使用他们,在使用他们之前,需要设置其可访问性为true。具体操作过程如下:

    private void newPrivateClass(String clazzName) {
            try {
                Class<?> clazz = Class.forName(clazzName);
                Constructor<?> constructor = clazz.getDeclaredConstructor();
                constructor.setAccessible(true);
                PrivateClass privateClass = (PrivateClass)constructor.newInstance();
                
                Method method = clazz.getDeclaredMethod("sayHello");
                method.setAccessible(true);
                method.invoke(privateClass);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    GitHub源码连接:

    https://github.com/William-Hai/TestReflect

  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/fengju/p/6336033.html
Copyright © 2011-2022 走看看