• Java基础教程:反射基础


    Java基础教程:反射基础

    引入反射

    反射是什么

      能够动态分析类能力的程序称为反射。反射是一种很强大且复杂的机制。

    Class类

      在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时的类型标识。这个对象追踪着每个对象所属的类。虚拟机利用运行时类的信息选择相应的方法执行

      我们可以通过专门的Java类访问这些信息。保存这些信息的类称为Class。

    直接获取

    Class cl1 =Date.class;
    Class cl2 = Integer.class;

    根据对象获得类信息

    MyClass myClass;
    .....
    Class cl = myClass.getClass();
    cl.getName(); //获得类名

    调用静态方法forName获得类名相应的Class对象。

    String className = 'java.util.Date';
    Class cl = Class.forName(className);

    注意:

      虚拟机为每一个类型管理一个Class对象。因此使用==可以实现两个类对象比较的操作

     

    利用反射分析类的能力

    API函数举例

    • getDeclaredFields():获得此类对象所表示的类或接口所声明的所有字段。
    • getFields():输出类以及其所继承的父类的 public 字段
    • getDeclaredMethods():获得此类对象所表示的类或接口所声明的所有方法,包括公共、保护、私有但不包括继承。
    • getDeclaredConstructors() :返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
    • getName():获得此class所表示实体的名称。

    示例:输出字段

      GetFields只会输出publicStr,GetDeclaredFields则会忽略访问控制符输出所有字段

    public class MyClass{
    
        public String publicStr;
        private String privateStr;
        protected String protectedStr;
    
        public static void main(String[] args) {
            //获取Class类
            Class c1 = MyClass.class;
            //调用GetFields()
            for(Field field : c1.getFields()){
                System.out.println(field.getName());
            }
            System.out.println("=============");
            //调用GetDeclaredFields()
            for(Field field : c1.getDeclaredFields()){
                System.out.println(field.getName());
            }
        }
    }

    示例:输出方法

      getDeclaredMethods只会输出本类的所有方法!

    public class MyClass{
    
        public void publicFun(int a){}
        private void privateFun(int a){}
        protected void protectFun(int a){}
    
        public static void main(String[] args) {
            //获取Class类
            Class c1 = MyClass.class;
    
            //2.1 获取所有 public 访问权限的方法
            //包括自己声明和从父类继承的
            //Method[] mMethods = c1.getMethods();
    
            //2.2 获取所有本类的的方法(不问访问权限)
            Method[] mMethods = c1.getDeclaredMethods();
    
            //3.遍历所有方法
            for (Method method :
                    mMethods) {
                //获取并输出方法的访问权限(Modifiers:修饰符)
                int modifiers = method.getModifiers();
                System.out.print(Modifier.toString(modifiers) + " ");
                //获取并输出方法的返回值类型
                Class returnType = method.getReturnType();
                System.out.print(returnType.getName() + " "
                        + method.getName() + "( ");
                //获取并输出方法的所有参数
                Parameter[] parameters = method.getParameters();
                for (Parameter parameter :
                        parameters) {
                    System.out.print(parameter.getType().getName()
                            + " " + parameter.getName() + ",");
                }
                //获取并输出方法抛出的异常
                Class[] exceptionTypes = method.getExceptionTypes();
                if (exceptionTypes.length == 0) {
                    System.out.println(" )");
                } else {
                    for (Class c : exceptionTypes) {
                        System.out.println(" ) throws "
                                + c.getName());
                    }
                }
            }
        }
    }

      调用getDeclaredMethods输出结果:

    • public static void main( [Ljava.lang.String; arg0, )
    • protected void protectFun( int arg0, )
    • private void privateFun( int arg0, )
    • public void publicFun( int arg0, )

      调用getMethods输出结果:

    • public static void main( [Ljava.lang.String; arg0, )
    • public void publicFun( int arg0, )
    • public final void wait( ) throws java.lang.InterruptedException
    • public final void wait( long arg0,int arg1, ) throws java.lang.InterruptedException
    • public final native void wait( long arg0, ) throws java.lang.InterruptedException
    • public boolean equals( java.lang.Object arg0, )
    • public java.lang.String toString( )
    • public native int hashCode( )
    • public final native java.lang.Class getClass( )
    • public final native void notify( )
    • public final native void notifyAll( )

     

    在运行时使用反射分析对象

    API函数举例

    • setAccessible(boolean flag):为反射对象设置可访问标志。为true使得对象的私有属性也可以被查询和设置。
    • getField(): 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
    • get(Object obj):返回对象中用Field对象表示的域值。
    • set(Object obj,Object newValue):用一个新值设置Obj对象中的Field对象表示的域。

    示例:获取并设置对象的私有字段值

    public class MyClass{
    
        private String context = "Hello World";
    
        public static void main(String[] args) {
            //获取Class类
            Class c1 = MyClass.class;
            try {
                //构建对象
                Object myClass = c1.newInstance();
                //获取私有变量
                Field context = c1.getDeclaredField("context");
                //获取私有变量访问权
                context.setAccessible(true);
                //访问私有变量值
                System.out.println(context.get(myClass));
                //设置私有变量值
                context.set(myClass, "Hi Boy!");
                System.out.println(context.get(myClass));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

     

    利用反射调用任意方法

    API函数说明

       public Object invoke(Object obj,Object... args)

    • 参数:obj - 从中调用底层方法的对象args - 用于方法调用的参数
    • 返回:使用参数 args 在 obj 上指派该对象所表示方法的结果

    示例:调用私有方法

    public class NCConfgCliService {
    
        private void privateFun(int a){
            System.out.println(a);
        }
    
        public static void main(String[] args) {
            //获取Class类
            Class c1 = NCConfgCliService.class;
            try {
                //获取私有方法
                Method privateMethod = c1.getDeclaredMethod("privateFun",int.class);
                //创建类的实例
                Object obj =  c1.newInstance();
                //调用私有方法
                privateMethod.invoke(obj,10);
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }
    

     

  • 相关阅读:
    .NET开源B2C商城项目AssionShop开始开发设计(发布3小时撤下)
    AssionShop开源B2C电子商务系统概述
    ASP.NET中在不同的子域中共享Session
    单元测试框架"艾信.NET单元测试工具(AssionUnit)"开发第二步
    asp.net mvc 分页控件 MvcPager修改;使用范围增大
    Linux服务器测试网络连通性
    如何使用python连接mysql数据库
    mysql数据库基础知识
    使用python创建数据库并插入数据
    Linux下查看日志用到的常用命令
  • 原文地址:https://www.cnblogs.com/MrSaver/p/8343828.html
Copyright © 2020-2023  润新知