利用注解完成变量自动初始化

利用注解完成对成员变量的自动初始化。应用场景,某应用分为很多个模块,为了简化后续开发人员配置新模块的工作,使项目维护更为容易,运用注解来对模块进行初始化。简单修改后可以成为类似ButterKnife的工具。

区别在于ButterKnife的注解类型是@Retention(RetentionPolicy.SOURCE)的,即源代码编译阶段发挥作用的注解,编译完后就丢弃了。而我用的是@Retention(RetentionPolicy.RUNTIME),也是书上用到的,即运行时的再生效的注解,使用反射来完成注解所要达成的目标,有一定的性能损耗。

ModuleEntry

先来看ModuleEntry类,每个该类对象表示一个模块。

public class ModuleEntry {
    int id;
    String name;
    String des;
    public ModuleEntry(int id, String name, String des) {
        this.id = id;
        this.name = name;
        this.des = des;
    }
}

Module注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Module {
    int id();
     //String value();//注意注解中名为value的元素,如果应用该注解时,value元素是唯一需要赋值的元素,那么只需在括号内给出value元素所需的值即可
    String moduleName() default "";
    String moduleDes() default "";
}

ModuleSet 注解

用以标识包含ModuleEntry的对象的类,我们将对这个类中的带有Module注解的元素进行自动初始化。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModuleSet {
    String value();//其实这里的value没有什么意义,是为了表示一下value元素的特殊,这点稍后会看到
}

Main函数

先看main函数,我最终想要实现的效果应该是其中的ModuleEntry对象都能根据注解自己初始化。

class Activity{}
@ModuleSet("Main")
class MainActivity extends Activity{
    @Module(id = 0,
            moduleName = "模块管理",
            moduleDes = "对模块进行管理")
    ModuleEntry mManagerModule;

    @Module(id = 1,
            moduleName = "校园网",
            moduleDes = "校园网管理")
    ModuleEntry mSeunetModule;

    ModuleEntry mOtherModule;
  
    public MainActivity(){
        ModuleHelper.configureModule(this);
    }
}

public class Main{
    public static void main(String[] args){
        MainActivity mainActivity = new MainActivity();
        System.out.println(mainActivity.mManagerModule.des);
        //NullPointerException,因为mOtherModule没有添加注解,不会被自动初始化
        //System.out.println(mainActivity.mOtherModule.des);
    }
}

而自动初始化是由ModuleHelper来完成的。

ModuleHepler

public class ModuleHelper {
    public static void configureModule(Activity activity){
        //输出传入对象类型
        System.out.println(activity.getClass());
        //查看其是否添加了ModuleSet注解并获取注解
        System.out.println(activity.getClass().isAnnotationPresent(ModuleSet.class));
        ModuleSet moduleSetAnnotation = activity.getClass().getAnnotation(ModuleSet.class);
        //必须添加了该注解的类才能使用这个方法,否则不做任何操作
        if (moduleSetAnnotation == null)return;
        
        //遍历所有的域
        for (Field field : activity.getClass().getDeclaredFields()){
            Module module = field.getAnnotation(Module.class);

            //如果没有模块注解,或者其类型不是模块实体,则跳过
            if(module == null || field.getType() != ModuleEntry.class)continue;
            //对所有的满足条件的Field,输出模块对应的名字和描述
            System.out.println(module.moduleName() + " " + module.moduleDes());
            System.out.println(field.getName());
            
            //生成模块条目
            ModuleEntry moduleEntry = new ModuleEntry(module.id(),module.moduleName(),module.moduleDes());
            try {
                field.setAccessible(true);
                //使用set函数可以为当前的field实际代表的对象进行赋值,如果是static对象则可以把第一个参数置为null
                field.set(activity,moduleEntry);
                //使用get函数可以获得这个对象
                //ModuleEntry moduleEntry0 = (ModuleEntry) field.get(activity);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

/**Output
class com.note.MainActivity
true
模块管理 对模块进行管理
mManagerModule
校园网 校园网管理
mSeunetModule
对模块进行管理
*/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JadePeng的技术博客

JavaScript 实现接口 (Interfaces In JavaScript)

接口是面向对象编程里的重要特性,遗憾的是JavaScript并没有提供对接口的支持!怎么实现接口呢? 在实际中,我们可以在注释中定义好接口,在实际的代码中予以实...

4176
来自专栏ImportSource

图解ByteBuffer

概述 ByteBuffer是NIO里用得最多的Buffer,它包含两个实现方式:HeapByteBuffer是基于Java堆的实现,而DirectByteBuf...

4065
来自专栏Flutter入门到实战

谈谈模板方法设计模式的使用

在项目中经常会遇到一个类的某些方法和另一个类的某些方法功能是相同的,只有部分方法是不同的。这个时候就可以使用模板方法来操作了。其实这种情况很常见:比如我们项目里...

892
来自专栏青玉伏案

Java编程之反射中的注解详解

“注解”这个词,可谓是在Java编程中出镜率比较高,而且也是一个老生常谈的话题。我们之前在聊Spring相关的东西时,注解是无处不在,之前我们简单的聊过一些“注...

1856
来自专栏java一日一条

框架开发之Java注解的妙用

2.本来可能需要很多配置文件,需要很多逻辑才能实现的内容,就可以使用一个或者多个注解来替代,这样就使得编程更加简洁,代码更加清晰。

1183
来自专栏技术小黑屋

详解Java中的注解

在Java中,注解(Annotation)引入始于Java5,用来描述Java代码的元信息,通常情况下注解不会直接影响代码的执行,尽管有些注解可以用来做到影响代...

811
来自专栏老马说编程

(85) 注解 / 计算机程序的思维逻辑

上节我们探讨了反射,反射相关的类中都有方法获取注解信息,我们在前面章节中也多次提到过注解,注解到底是什么呢? 在Java中,注解就是给程序添加一些信息,用字符...

2325
来自专栏Android 研究

Retrofit解析4之注解

由于Retrofit里面大量的用到了注解,为了让大家更好的学习Retrofit,特意准备了一篇Java注解,如果大家已经对Java注解已经很熟悉了,就略过,看下...

2394
来自专栏Android先生

[译]Android防止内存泄漏的八种方法(下)

在上一篇Android内存泄漏的八种可能(上)中,我们讨论了八种容易发生内存泄漏的代码。其中,尤其严重的是泄漏Activity对象,因为它占用了大量系统内存。不...

872
来自专栏专注 Java 基础分享

JAVA 注解的基本原理

以前,『XML』是各大框架的青睐者,它以松耦合的方式完成了框架中几乎所有的配置,但是随着项目越来越庞大,『XML』的内容也越来越复杂,维护成本变高。

1393

扫码关注云+社区

领取腾讯云代金券