Java Android-可以将@IntDef值放在@interface中吗?
我试图在Android开发中实现Java Android-可以将@IntDef值放在@interface中吗?,java,android,annotations,Java,Android,Annotations,我试图在Android开发中实现@IntDef注释 第一个方法:将定义分隔在一个常量中看起来很棒。java类: public class Constant { @IntDef(value={SORT_PRICE, SORT_TIME, SORT_DURATION}) @Retention(RetentionPolicy.SOURCE) public @interface SortType{} public static final int SORT_PRICE = 0;
@IntDef
注释
第一个方法:将定义分隔在一个常量中看起来很棒。java
类:
public class Constant {
@IntDef(value={SORT_PRICE, SORT_TIME, SORT_DURATION})
@Retention(RetentionPolicy.SOURCE)
public @interface SortType{}
public static final int SORT_PRICE = 0;
public static final int SORT_TIME = 1;
public static final int SORT_DURATION = 2;
}
用法:
@Constant.SortType int sortType = Constant.SORT_PRICE;
@Constant.SortTypeDef int sortType = Constant.SortType.PRICE;
但是,当一个文件中有多个定义(例如UserType、StoreType等)时,事情会变得更加混乱
第二种方法:因此我提出了类似的方法来区分定义之间的值:
public class Constant {
@IntDef(value={SortType.SORT_PRICE, SortType.SORT_TIME, SortType.SORT_DURATION})
@Retention(RetentionPolicy.SOURCE)
public @interface SortTypeDef{}
public static class SortType{
public static final int PRICE = 0;
public static final int TIME = 1;
public static final int DURATION = 2;
}
}
用法:
@Constant.SortType int sortType = Constant.SORT_PRICE;
@Constant.SortTypeDef int sortType = Constant.SortType.PRICE;
但正如您所看到的,我为它创建了两个不同的名称:SortTypeDef
和SortType
第三种方法:我试图在@界面中移动可能值的列表
:
public class Constant {
@IntDef(value={SortType.SORT_PRICE, SortType.SORT_TIME, SortType.SORT_DURATION})
@Retention(RetentionPolicy.SOURCE)
public @interface SortType{
int PRICE = 0;
int TIME = 1;
int DURATION = 2;
}
}
用法
@Constant.SortType int sortType = Constant.SortType.PRICE;
虽然它确实有效,但我不知道它的缺点是什么。
可以将
@IntDef
的可能值放入@interface
中吗?以上三种方法的性能有什么不同吗?似乎是枚举的好地方
public enum SortEnum {
DURATION,
PRICE,
TIME;
}
我来这里是想知道为什么Android文档会显示你的第一种方法,但是第三种方法在我的生产代码中已经运行了好几个月了。我看不出有什么理由不那样做。正如您所说,当您可能有多组相关常量时,它会清理名称空间。要使第三个方法工作,您应该像在界面中一样命名
值。
我使用了您的代码并使其正常工作:
public class Constant {
@IntDef(value = {SortType.PRICE, SortType.TIME, SortType.DURATION})
@Retention(RetentionPolicy.SOURCE)
@interface SortType {
int PRICE = 0;
int TIME = 1;
int DURATION = 2;
}
}
或
第二种用法:
@Constant.SortType int sortType = Constant.SortType.SORT_DURATION;
选择一个,两者都应该有效。简短回答:对于简单的项目,这是可以的,但对于更复杂的项目,首选第一种方法
长答案:
虽然sortType
的字节码在所有三种情况下都是相同的,但存在差异。关键在于Retention
注释,它将保留策略设置为SOURCE
。这意味着您的SortType
注释是“”,因此不会生成注释本身的字节码
第一个方法在注释之外定义常规静态字段,并为它们生成常规字节码。第二种和第三种情况在注释中定义常量,并且不会生成常量的字节码
如果编译器可以访问包含SortType
声明的源文件,则两种方法都可以,并且SortType
的字节码是相同的。但如果源代码不可访问(例如,您只有编译过的库),则无法访问注释。对于第一种方法,只有注释本身是不可访问的,但是对于后一种方法,常量值也是不可访问的
我过去更喜欢第三种方法,因为它最干净、最有条理。直到有一天我遇到了一个问题:当我开始为代码编写浓缩咖啡测试时,编译器无法访问定义注释的源代码。我必须切换到规范的IntDef
声明,或者在测试中使用整数值而不是符号常量
因此,底线是:
- 除非注释是代码内部的,并且您不从任何其他地方(包括测试)引用它,否则请坚持使用规范方法
您找到这个问题的解决方案了吗?我现在也在想同样的问题…@IgorGanapolsky还没有,但我继续在生产代码上使用第三种方法,到目前为止没有问题。我认为最好的检查方法是分析(用法、常量数等)。IntDef注释只有RetentionPolicy.SOURCE,因此仅由编译器注释处理器使用。它不可能对运行时性能产生影响,除非注释处理器正在做一些非常深奥的事情,例如使用字节码编织或代码生成将运行时检查插入到代码中。idk,自从我观看之后,我一直在避免使用enum。假设视频是2 y.o,并且很多事情可能已经发生了变化。Intdef是专门为资源受限系统中的枚举替换而设计的。建议用Enum替换它们既不能回答问题,也无助于对话。在Ahmad指出之前,他并不知道Android中的Enum问题。我一直在使用Java,但直到最近才使用Android,在我看来OP实现了一种反模式。但是,由于在Android上研究枚举的问题,我将避免使用它们,并检查IntDefs。@Nineplan失败如果使用proguard,您可以毫无问题地使用枚举,因为proguard将在编译发布时替换它们。