美文网首页测试
java反射的应用场景和解析方法

java反射的应用场景和解析方法

作者: 测试你个头 | 来源:发表于2017-03-16 11:26 被阅读901次

    提到java语言的高级特性,反射绝对是Top1级别的,在大量开源框架中的应用范例比比皆是,那么需要了解清楚反射到底是什么?为什么要使用反射?如何使用反射?(what,why,how)

    什么是反射?

    正常场景下,java从源码到运行有3个阶段:
    source class runtime

    反射提供的是runtime阶段获取类的class实例、方法、属性、注解,并且能够调用类的方法的途径,这种动态获取类信息和调用类方法的机制被称之为反射

    为什么要使用反射?

    正常的实例化一个对象

    ClassA objA = new ClassA();
    objA.sayHello();
    

    通过反射去实例化一个对象

    ClassA objA  = (ClassA)ClassA.class.newInstance();
    Method method = objA.getMethod("sayHello");
    method.invoke();
    

    在source阶段实际上二者并无任何区别,反射也没有体现出任何的优势,那么任何一个java开发人员必然会问为什么要使用反射?
    反射的重点在于runtime阶段的获取类信息和调用类方法,那么当你的编码过程中中有“部分信息是source阶段不清晰,需要在runtime阶段动态临时加载”这种场景,反射就可以派上用场了

    我们考虑几个编码场景:
    1、编码阶段不知道需要实例化的类名是哪个,需要在runtime从配置文件中加载:

    Class clazz = class.forName("xxx.xxx.xxx")
    clazz.newInstance();
    

    2、在runtime阶段,需要临时访问类的某个私有属性

    ClassA objA = new ClassA();
    Field xxx = objA.getClass().getDeclaredField("xxx")
    xxx.setAccessible(true);
    

    所以,反射的优点在于“有些编码需求在source阶段无法实现,只能在runtime阶段通过反射实现”,而非“source阶段正常编码方式能解决的,反射的方式能解决的更好”,所以比较反射和正常编码方式的优劣是没有意义的,反射解决的是正常编码无法解决的编码场景,如果正常编码方式可以解决的,强行使用反射反而是毫无意义的,编码不是为了show技巧。

    反射应用范例代码

    实现对类或者对象的构造器、方法、属性、注解的获取和操作,具体作用见代码中的注释描述

    public class ReflectionHelper {
    
        /**
         * Reflection Test Code
         *
         * @param args
         */
        public static void main(String[] args) {
            SSHClient sshClient = new SSHClient();
    
            // 获取class名称
            System.out.println("01-----获取class名称-----");
            System.out.println(sshClient.getClass().getName());
            System.out.println(sshClient.getClass().getSimpleName());
            System.out.println(sshClient.getClass().getTypeName());
    
            Class<?> clazz1 = null;
            Class<?> clazz2 = null;
            Class<?> clazz3 = null;
    
            // 获取对象或者类的Class实例
            try {
                clazz1 = Class.forName(sshClient.getClass().getName());
                clazz2 = sshClient.getClass();
                clazz3 = ReflectionUtils.class;
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            // 获取类的构造函数,用构造函数实例一个对象
            for (Constructor<?> clazz1Cstor : clazz1.getConstructors()) {
                System.out.println(clazz1Cstor.getName());
                try {
                    SSHClient client1 = (SSHClient) clazz1.newInstance();
                    SSHClient client2 = (SSHClient) clazz1Cstor.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
    
            }
    
            // 获取类定义的方法、属性
            System.out.println("02-----获取类定义的方法、属性-----");
            try {
                SSHClient client = (SSHClient) clazz1.newInstance();
                Method setHostMethod = clazz1.getDeclaredMethod("setHost", String.class);
                setHostMethod.invoke(client, "111");
    
                Field field = client.getClass().getDeclaredField("host");
                field.setAccessible(true);
                System.out.println(field.get(client));
                field.set(client,"a new host");
                System.out.println(field.get(client));
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
    
            // 获取类的注解
            System.out.println("03-----获取类使用的注解-----");
            for (Annotation annotation : clazz1.getAnnotations()) {
                System.out.println(annotation.getClass().getName());
                System.out.println(annotation.toString());
                System.out.println(annotation.annotationType());
            }
        }
    }
    

    运行结果:


    相关文章

      网友评论

      • Java_Pro:ClassA objA = (ClassA)ClassA.class.newInstance();
        Method method = objA.getMethod("sayHello");
        method.invoke();
        上述应该写成下面这样吧
        Class<ClassA> objA=ClassA.class;
        Method method=objA.getMethod("sayHello");
        method.invoke(objA.newInstance());
        测试你个头:对的,实际敲了下代码有问题,我fix下:

        Class objA = null;

        try {

        objA = TagInfoService.class;

        Method method = objA.getMethod("creatTag");

        method.invoke(objA.newInstance());

        } catch (InstantiationException e) {

        e.printStackTrace();

        } catch (IllegalAccessException e) {

        e.printStackTrace();

        } catch (NoSuchMethodException e) {

        e.printStackTrace();

        } catch (InvocationTargetException e) {

        e.printStackTrace();

        }
      • c397b5a6deec:java.lang.NoSuchMethodException: Iterator.SSHClient.setHost(java.lang.String)
        at java.lang.Class.getMethod(Class.java:1786)
        at Iterator.ReflectHelper.main(ReflectHelper.java:54)
        我运行之后报这个错误是怎么来的?
        测试你个头:我这里范例代码不全,没有SSHClient类

      本文标题:java反射的应用场景和解析方法

      本文链接:https://www.haomeiwen.com/subject/ykejittx.html