use*_*312 65 java enums annotations
我无法使用从常量中取得的枚举作为注释中的参数.我得到这个编译错误:"注释属性[attribute]的值必须是枚举常量表达式".
这是Enum代码的简化版本:
public enum MyEnum {
APPLE, ORANGE
}
Run Code Online (Sandbox Code Playgroud)
对于注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface MyAnnotation {
String theString();
int theInt();
MyEnum theEnum();
}
Run Code Online (Sandbox Code Playgroud)
和班级:
public class Sample {
public static final String STRING_CONSTANT = "hello";
public static final int INT_CONSTANT = 1;
public static final MyEnum MYENUM_CONSTANT = MyEnum.APPLE;
@MyAnnotation(theEnum = MyEnum.APPLE, theInt = 1, theString = "hello")
public void methodA() {
}
@MyAnnotation(theEnum = MYENUM_CONSTANT, theInt = INT_CONSTANT, theString = STRING_CONSTANT)
public void methodB() {
}
}
Run Code Online (Sandbox Code Playgroud)
该错误仅出现在methodB上的"theEnum = MYENUM_CONSTANT"中.字符串和int常量对编译器来说是可以的,但枚举常量不是,即使它与方法A上的值完全相同.在我看来,这是编译器中缺少的功能,因为这三个显然都是常量.没有方法调用,没有奇怪的类使用等.
我想要实现的是:
任何实现这些目标的方法都没问题.
编辑:
谢谢大家.正如你所说,它无法完成.应该更新JLS.我这次决定忘记注释中的枚举,并使用常规的int常量.只要int是从命名常量赋值的,值就是有界的,并且它的"类型"类型是安全的.
它看起来像这样:
public interface MyEnumSimulation {
public static final int APPLE = 0;
public static final int ORANGE = 1;
}
...
public static final int MYENUMSIMUL_CONSTANT = MyEnumSimulation.APPLE;
...
@MyAnnotation(theEnumSimulation = MYENUMSIMUL_CONSTANT, theInt = INT_CONSTANT, theString = STRING_CONSTANT)
public void methodB() {
...
Run Code Online (Sandbox Code Playgroud)
我可以在代码中的任何其他地方使用MYENUMSIMUL_CONSTANT.
Iva*_*tov 90
"计算机科学中的所有问题都可以通过另一层次的间接解决"--- David Wheeler
这里是:
枚举类:
public enum Gender {
MALE(Constants.MALE_VALUE), FEMALE(Constants.FEMALE_VALUE);
Gender(String genderString) {
}
public static class Constants {
public static final String MALE_VALUE = "MALE";
public static final String FEMALE_VALUE = "FEMALE";
}
}
Run Code Online (Sandbox Code Playgroud)
人员类:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = Person.GENDER)
@JsonSubTypes({
@JsonSubTypes.Type(value = Woman.class, name = Gender.Constants.FEMALE_VALUE),
@JsonSubTypes.Type(value = Man.class, name = Gender.Constants.MALE_VALUE)
})
public abstract class Person {
...
}
Run Code Online (Sandbox Code Playgroud)
ass*_*ias 20
它似乎在JLS#9.7.1中定义:
[...] V的类型与T分配兼容(第5.2节),此外:
- [...]
- 如果T是枚举类型,则V是枚举常量.
枚举常量定义为实际枚举常量(JLS#8.9.1),而不是指向该常量的变量.
底线:如果您想使用枚举作为注释的参数,则需要为其指定显式的MyEnum.XXXX值.如果要使用变量,则需要选择其他类型(不是枚举).
一种可能的解决方法是使用String或int,然后可以将其映射到枚举 - 您将失去类型安全性,但可以在运行时轻松发现错误(=在测试期间).
Jea*_*ean 20
我认为投票最多的答案是不完整的,因为它根本不能保证枚举值与基础常String
数值相结合.有了这个解决方案,人们应该将这两个类分开.
相反,我建议通过强制枚举名称和常量值之间的相关性来强化该答案中显示的耦合,如下所示:
public enum Gender {
MALE(Constants.MALE_VALUE), FEMALE(Constants.FEMALE_VALUE);
Gender(String genderString) {
if(!genderString.equals(this.name()))
throw new IllegalArgumentException();
}
public static class Constants {
public static final String MALE_VALUE = "MALE";
public static final String FEMALE_VALUE = "FEMALE";
}
}
Run Code Online (Sandbox Code Playgroud)
另外,应该编写单元测试,检查字符串是否为常量.
控制规则似乎是"如果T是枚举类型,V是枚举常量.",9.7.1.正常注释.从文本中可以看出,JLS的目标是对注释中的表达式进行极其简单的评估.枚举常量特别是枚举声明中使用的标识符.
即使在其他情况下,使用枚举常量初始化的最终值似乎也不是常量表达式.4.12.4.最终变量说"原始类型或类型String的变量,是最终的并用编译时常量表达式(第15.28节)初始化,称为常量变量.",但不包括用枚举初始化的枚举类型的最终结果.枚举常数.
我还测试了一个简单的例子,其中表达式是否是一个常量表达式 - 如果围绕对未赋值变量的赋值.该变量未被分配.测试最终int的相同代码的替代版本确实使变量明确赋值:
public class Bad {
public static final MyEnum x = MyEnum.AAA;
public static final int z = 3;
public static void main(String[] args) {
int y;
if(x == MyEnum.AAA) {
y = 3;
}
// if(z == 3) {
// y = 3;
// }
System.out.println(y);
}
enum MyEnum {
AAA, BBB, CCC
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
52925 次 |
最近记录: |