迭代@ IntDef,@ StringDef或任何@Def类

时间:2015-08-22 20:18:41

标签: java bitflags

考虑这个课程:

public class MyClassOfMystery {

    public static final int NO_FLAGS = ~0;
    public static final int FIRST_FLAG = 1;
    public static final int SECOND_FLAG = 1 << 1;
    public static final int THIRD_FLAG = 1 << 2;
    public static final int FOURTH_FLAG = 1 << 3;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, value = {NO_FLAGS, FIRST_FLAG, SECOND_FLAG, THIRD_FLAG, FOURTH_FLAG})
    public @interface MysteryFlags { }

   ... set flags, get flags, and use flags stuff.
}

我经常创建这样的东西,并发现能够遍历MysteryFlags中可用的所有标志会很有用。

我可以遍历MysteryFlags中设置的值吗?

这就是我的尝试:

打印ANNOTATION: @java.lang.annotation.Retention(value=SOURCE)

for (Annotation annotation : Flag.class.getAnnotations()) {
   Log.d(TAG, String.format("ANNOTATION: %s", String.valueOf(annotation)));
}

这将NPE置于空数组访问

for (ExtraAction enm : Flag.class.getEnumConstants()) {
   Log.d(TAG, String.format("ENUM: %s", String.valueOf(enm)));
}

这些没有打印出任何东西:

for (Field field : Flag.class.getFields()) {
   Log.d(TAG, String.format("FIELD: %s", String.valueOf(field)));
}

for (Class<?> aClass : ExtraAction.class.getClasses()) {
        Log.d(TAG, String.format("CLASS: %s", String.valueOf(aClass)));
}

我知道我可以将值添加到数组并迭代它,但这需要存储另一个数组。这就是我所做的,但仍然想知道是否有更好的方法。

3 个答案:

答案 0 :(得分:8)

我不认为您能够在运行时查询它。您的@MysterFlags注释的保留策略为SOURCE,这意味着编译器会将其丢弃。此外,@IntDef注释的保留策略为CLASS,这意味着它通过编译实现,但不会使其成为运行时。这就是为什么您只在第一个循环中看到@Retention注释的原因(该注释的保留政策为RUNTIME)。

答案 1 :(得分:0)

好吧,这可能有点老了-但是我遇到了类似的问题,发现的解决方案是:

MysteryFlags.class.getDeclaredFields()

它将返回所有声明的定义。

答案 2 :(得分:0)

如果我们在@interface本身内声明字段,则可以做出妥协

@Retention(RetentionPolicy.SOURCE)
@IntDef({MysteryFlags.NO_FLAGS, MysteryFlags.FIRST_FLAG, MysteryFlags.SECOND_FLAG, MysteryFlags.THIRD_FLAG, MysteryFlags.FOURTH_FLAG})
public @interface MysteryFlags {

    // Note that all fields declared in an interface are implicitly public static final
    int NO_FLAGS = ~0;
    int FIRST_FLAG = 1;
    int SECOND_FLAG = 1 << 1;
    int THIRD_FLAG = 1 << 2;
    int FOURTH_FLAG = 1 << 3;
}

getFields()上调用MisteryFlags.class时,将返回注释中声明的所有字段。

但是,这意味着@interface中未定义的@IntDef中的任何字段也将被返回。 IMO,如果遵循严格的协议来实施,那么效果会很好。