java高级编程--反射机制(Reflection)

java反射机制的概述

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
反射机制的特征:动态性

有反射VS无反射

一:无反射时可对类的操作

  1. 创建类的对象实例;
  2. 通过对象实例调用内部的属性方法。
  3. 在类的外部不能通过该类对象调用其内部私有的结构(体现了面向对象的封装性)

二:有反射是可对类的操作
1. 通过反射创建类的对象
2. 通过反射调用其对象的属性方法
3. 可调用类的所有结构
4. 可调用注解。

java.long.Class的理解

一:.类的加载过程:
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。 接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件 加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此 运行时类,就作为Class的一个实例。Class的实例就对应着一个运行时类。加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式 来获取此运行时类。
获取运行时类的方式

  1. 调用运行时类的属性(类名.class)
    假设此类为Person类,以下举例权益Person为例
Class clazz1 = Person.class;
  1. 通过运行时类的对象创建运行时类(getClass())
Person p1 = new Person();
Class clazz2 = p1.getClass();
  1. 调用class是的静态方法:forName(String classPath)
    其中classPath为全类名
Class clazz = Class.forName("全类名");
  1. 类的加载器ClassLoader
 ClassLoader classLoader = Person.class.getClassLoader();
 Class clazz4 = classLoader.loadClass("全类名");

newInstance()方法

调用此方法,创建对应的运行时类的对象。
使用此方法的注意点

  1. 运行时类必须提供空参的构造器;
  2. 空参的构造器的访问权限设置为public。
Class<Person> clazz = Person.class;
Person obj = clazz.newInstance();

通过反射获取运行时类的完整结构

一:运行时类的属性(getFields() VS getDeclaredFields())

  • getFields():获取当前运行时类及其父类中声明为public访问权限的属性
  • getDeclaredFields()获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
 Class clazz = Person.class;

        //获取属性结构
        //getFields():获取当前运行时类及其父类中声明为public访问权限的属性
        Field[] fields = clazz.getFields();
        for(Field f : fields){
            System.out.println(f);
        }
        System.out.println();

        //getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f : declaredFields){
            System.out.println(f);
        }

二:权限修饰符(getModifiers())数据类型(getType())变量名(getName())

        Class clazz = Person.class;
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f : declaredFields){
            //1.权限修饰符
            int modifier = f.getModifiers();
            System.out.print(Modifier.toString(modifier) + "\t");

            //2.数据类型
            Class type = f.getType();
            System.out.print(type.getName() + "\t");

            //3.变量名
            String fName = f.getName();
            System.out.print(fName);

            System.out.println();
        }

获取运行时类的方法(getMethods() VS getDeclaredMethods())

  • getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
  • getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)
        Class clazz = Person.class;

        //getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
        Method[] methods = clazz.getMethods();
        for(Method m : methods){
            System.out.println(m);
        }
        System.out.println();
        //getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for(Method m : declaredMethods){
            System.out.println(m);
        }
/**
@注解
权限修饰符  返回值类型  方法名(参数类型1 形参名1,...) throws XxxException{}
*/
        Class clazz = Person.class;
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for(Method m : declaredMethods){
            //1.获取方法声明的注解
            Annotation[] annos = m.getAnnotations();
            for(Annotation a : annos){
                System.out.println(a);
            }

            //2.权限修饰符
            System.out.print(Modifier.toString(m.getModifiers()) + "\t");

            //3.返回值类型
            System.out.print(m.getReturnType().getName() + "\t");

            //4.方法名
            System.out.print(m.getName());
            System.out.print("(");
            //5.形参列表
            Class[] parameterTypes = m.getParameterTypes();
            if(!(parameterTypes == null && parameterTypes.length == 0)){
                for(int i = 0;i < parameterTypes.length;i++){

                    if(i == parameterTypes.length - 1){
                        System.out.print(parameterTypes[i].getName() + " args_" + i);
                        break;
                    }

                    System.out.print(parameterTypes[i].getName() + " args_" + i + ",");
                }
            }

            System.out.print(")");

            //6.抛出的异常
            Class[] exceptionTypes = m.getExceptionTypes();
            if(exceptionTypes.length > 0){
                System.out.print("throws ");
                for(int i = 0;i < exceptionTypes.length;i++){
                    if(i == exceptionTypes.length - 1){
                        System.out.print(exceptionTypes[i].getName());
                        break;
                    }

                    System.out.print(exceptionTypes[i].getName() + ",");
                }
            }

获取运行时类中指定的结构、属性、方法、构造器

属性的获取
  1. 创建运行时类的对象
  2. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
  3. 保证当前属性是可访问的setAccessible(true);
  4. 设置指定对象的此属性值
        Class clazz = Person.class;

        //1.创建运行时类的对象
        Person p = (Person) clazz.newInstance();

        //2. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
        Field name = clazz.getDeclaredField("name");

        //3.保证当前属性是可访问的
        name.setAccessible(true);
        //4.获取、设置指定对象的此属性值
        name.set(p,"Tom");

        System.out.println(name.get(p));
运行时类中的指定的方法
  1. 创建运行时类的对象
  2. 获取指定的某个方法的getDeclaredMethod(参数1,参数2)
    参数1:指明获取方法方法的名称;
    参数2:指明获取的方法的形参列表
  3. 保证当前方法是可访问的setAccessible(true)
  4. 调用方法的invoke(参数1,参数2)
    参数1:方法调用者
    参数2:需要赋值的实参
        Class clazz = Person.class;

        //1.创建运行时类的对象
        Person p = (Person) clazz.newInstance();

        /*
        2.获取指定的某个方法
        getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表
         */
        Method show = clazz.getDeclaredMethod("show", String.class);
        //3.保证当前方法是可访问的
        show.setAccessible(true);

        /*
        4. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
        invoke()的返回值即为对应类中调用的方法的返回值。
         */
        Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");
        System.out.println(returnValue);
运行时类的指定构造器
        Class clazz = Person.class;

        //private Person(String name)
        /*
        1.获取指定的构造器
        getDeclaredConstructor():参数:指明构造器的参数列表
         */

        Constructor constructor = clazz.getDeclaredConstructor(String.class);

        //2.保证此构造器是可访问的
        constructor.setAccessible(true);

        //3.调用此构造器创建运行时类的对象
        Person per = (Person) constructor.newInstance("Tom");
        System.out.println(per);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值