欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用@IntDef和@StringDef代替Java枚举

程序员文章站 2022-05-21 08:18:59
...

最近看别人的代码,发现别人使用了@IntDef的注解,便上网搜了一圈记录下来。

定义

Google文档是这样说的

Use the @IntDef and @StringDef annotations so you can create enumerated annotations of integer and string sets to validate other types of code references. Typedef annotations ensure that a particular parameter, return value, or field references a specific set of constants. They also enable code completion to automatically offer the allowed constants.

就是可以通过@IntDef和@StringDef创建枚举注解来验证你的代码引用是否正确,编译器自动检查也会对此校验。

使用

一般我们用静态常量来替代枚举,比如一年四季,一周七天,九大行星,七大洲等这些固定的值:

    public static final int SPRING = 1;
    public static final int SUMMER = 2;
    public static final int AUTUMN = 3;
    public static final int WINTER = 4;

但是这样写有些小问题,设置季节的时候可以设置任意int值,导致程序的健壮性不是很好。所以就引出了枚举:

    enum Season {
        SPRING, SUMMER, AUTUMN, WINTER
    }

这样setSeason()就不会设置成其他值,只能是枚举中的其中一个值。
但是各种Android性能优化告诉我们,尽量少用枚举,枚举消耗的内存比定义成常量更多。(其实少用点枚举也没多大关系,只有在内存紧张的时候才会考虑),因此,谷歌就推出了@IntDef和@StringDef注解。

首先,加入依赖:

compile 'com.android.support:support-annotations:22.0.0'

然后,定义静态常量:

    public static final int SPRING = 1;
    public static final int SUMMER = 2;
    public static final int AUTUMN = 3;
    public static final int WINTER = 4;

为这些常量声明@IntDef:

    @IntDef({SPRING, SUMMER,AUTUMN,WINTER})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Season {}

@Retention是Java里的注解内容,用于指定被修饰的Annotation可以保留多长时间:

  • RetentionPolicy.CLASS 默认值,编译器将把Annotation记录在class文件中。当运行Java程序时,JVM不再保留Annotation。
  • RetentionPolicy.RUNTIME 编译器将把Annotation记录在class文件中。当运行Java程序时,JVM也会保留Annotation。程序可以通过反射获取该Annotation信息。
  • RetentionPolicy.SOURCE Annotation只保留在源代码中,编译器直接丢弃这种Annotation。

接下来我们使用的时候:

    @Season int currentDay ;

    public void setCurrentDay(@Season int currentDay) {
        this.currentDay = currentDay;
    }
 
    @Season
    public int getCurrentDay() {
      return currentDay;
    }

这样就完成了,既不用枚举,常量也不会乱定义的问题。@StringDef用法一样,就是常量定义的是String类型。

参考