前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java之invoke与方法参数注解

Java之invoke与方法参数注解

作者头像
大话swift
发布2019-09-17 15:57:59
3.4K0
发布2019-09-17 15:57:59
举报
文章被收录于专栏:大话swift大话swift

上一节中我们说了Java之中非常主要的一个实例---注解的入门,这节我们结合反射中的invoke动态调用看看注解的作用域问题

继承是Java的一个重要特性而覆写是Java继承中不可获取的,而编辑器对于覆写的地方会只能添加Override对于这些大家都是习以为常了。但是这个是必须的吗?NO……去掉Override自己手动编译Java程序的时候依然没问题,这是为什么?我们先看看啥么是Override

代码语言:javascript
复制
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

Java源码中这么解释:1 Override只是说明告诉开发者这个方法是被覆写啦,并未功能性的含义。还有这个是给编辑器看的也就是做idea开发人员需要开发的功能

看了这些对我们有什么用呢?这个是为了引入今天注解是有它的作用环境和作用域的引子,我们来看看上栗注解的构成

@Target 代表这个注解标注的目标(往下看可以看出这个也是个注解)

代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

Target自身也是个注解,它的内部返回的是个数组枚举:以此来获取这个注解实用的对象---TYPE ,FIELD,METHD ……

@Retention

代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

这个代表注解在Java编译运行是这个注解所处的位置和运行时怎么使用,也就是说是在源码文件中还是在编译后的文件中甚至是动态获取

综合就是---Target在代码层次确定目标目标位置 Retention面向底层确定底层怎么使用

理论一大堆,我们结合之前一块看看怎么使用

先看代码后解读

代码语言:javascript
复制
 void run(@AnimalBean(animal = "com.company.Duck") Animal animal) {
      System.out.println("run before");
        animal.move();
        System.out.println("run after");
    }

这次我们把注解放置到方法的参数位置---参数注解,对应的我们需要修改我们的注解让其可以在runtime时使用,它修饰目标为方法参数

代码语言:javascript
复制

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,ElementType.TYPE, ElementType.METHOD})
@interface AnimalBean {
    String animal();
}

常规调用方式是new一个对象然后调用方法,但是这样我们就没法使用注解啦。那么我们怎么使用呢?其实这个时候需要的就是另一个方式invoke动态调用

代码语言:javascript
复制
 public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException{
           …………
           }

在Java的层面Class实例可以动态创建,方法可以动态绑定创建

代码语言:javascript
复制
 Object strInstance = Class.forName("java.lang.String").newInstance();
    Method strMethod = strInstance.getClass().getDeclaredMethod("toString");
       strMethod.invoke(strInstance);

当然了这里看不到数据输出--没有赋值,那么看看如何使用这个样的特性实现我们的run方法呢?

代码语言:javascript
复制
 AnimalFactory factory = new AnimalFactory();

        Method method = factory.getClass().getDeclaredMethod("run", Animal.class);
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            if (parameter.isAnnotationPresent(AnimalBean.class)) {
                AnimalBean animalBean = parameter.getAnnotation(AnimalBean.class);
                String animalName = animalBean.animal();
                Animal animalObj = (Animal) Class.forName(animalName).newInstance();
                Object result = method.invoke(factory, animalObj);
                System.out.println(result);
            }
        }

我们创建了实例AnimalFactory factory = new AnimalFactory(),然后获取Class和Method和然后根据参数的注解动态创建出了Animal,最后invoke调用

代码语言:javascript
复制
 Object result = method.invoke(factory, animalObj);

实现了通过注解完成参数的动态解析,当然这个是内部基本的实现逻辑思维,现实中我们不会一步步这么写,我们会采用Spring框架实现……

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大话swift 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档