美文网首页测试
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高级知识

    反射 sczyh30 深入解析Java反射(1) - 基础深入解析Java反射(2) - invoke方法深入探究...

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

    提到java语言的高级特性,反射绝对是Top1级别的,在大量开源框架中的应用范例比比皆是,那么需要了解清楚反射到底...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Feign源码学习(2)

    ReflectiveFeign 从Feign的使用方法我们可以推测,它的内部实现是利用了Java反射解析Api方法...

  • 安卓反射和动态代理的应用

    提纲 java反射基础 反射在Android中的应用 Java动态代理 动态代理在Android的应用 java反...

  • Java基础-反射-反射常见应用场景

    Java工程师知识树[https://www.jianshu.com/p/db77d19a25f6] / Ja...

  • iOS 反射

    什么是反射 类名、方法名、属性名和字符串在运行时相互转化的能力 反射方法 应用场景 1、代码模块化,解耦代码 2、...

  • Java反射理解(五)-- 方法反射的基本操作

    Java反射理解(五)-- 方法反射的基本操作 方法的反射 1. 如何获取某个方法 方法的名称和方法的参数列表才能...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

网友评论

  • 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