我认为这在Java中可能是不可能的,因为在编译时解析了注释及其参数。我有一个如下界面,
public interface FieldValues {
String[] FIELD1 = new String[]{"value1", "value2"};
}
和另一个类,
@SomeAnnotation(locations = {"value1", "value2"})
public class MyClass {
....
}
我使用注释标记了许多类,我想知道是否可以避免在每个注释中指定字符串而不是使用
@SomeAnnotation(locations = FieldValues.FIELD1)
public class MyClass {
....
}
然而,这会产生编译错误,例如注释值应该是数组初始化器等。有人知道如何使用String常量或String []常量来为注释提供值吗?
答案 0 :(得分:110)
编译常量can only be primitives and Strings:
<强> 15.28。常量表达式
编译时常量表达式是表示基本类型值的表达式或不突然完成的字符串,仅使用以下内容组成:
- 原始类型的文字和
类型的文字String
- 转换为基本类型并转换为
类型String
- [...]运营商[...]
- 包含表达式为常量表达式的带括号的表达式。
- 引用常量变量的简单名称。
- 表单 TypeName 的合格名称。引用常量变量的标识符。
实际上在java中没有办法保护数组中的项目。在运行时,有人可以总是FieldValues.FIELD1[0]="value3"
,因此如果我们看得更深,那么数组就不能真正保持不变。
答案 1 :(得分:33)
您可以使用常量(即静态最终变量)作为注释的参数。作为一个简单的例子,我经常使用这样的东西:
import org.junit.Test;
import static org.junit.Assert.*;
public class MyTestClass
{
private static final int TEST_TIMEOUT = 60000; // one minute per test
@Test(timeout=TEST_TIMEOUT)
public void testJDK()
{
assertTrue("Something is very wrong", Boolean.TRUE);
}
}
请注意,可以将TEST_TIMEOUT
常量直接传递给注释。
另外,我不记得曾经用数组试过这个,所以你可能会遇到一些问题,与Java变量相比,数组如何表示为注释参数?但至于问题的其他部分,你绝对可以使用一个常量字符串而没有任何问题。
编辑:我刚刚尝试使用String数组,并没有遇到你提到的问题 - 但编译器确实告诉我“属性值必须是常量”尽管数组定义为public static final String[]
。也许它不喜欢数组是可变的这个事实?嗯...
答案 2 :(得分:10)
在示例中,您没有为它提供数组。以下编译正常:
public @interface SampleAnnotation {
String[] sampleValues();
}
public class Values {
public static final String v1 = "A";
public static final String v2 = "B";
@SampleAnnotation(sampleValues = { v1, v2 })
public void foo() {
}
}
答案 3 :(得分:7)
有人知道如何使用 字符串常量或String []常量 为注释提供价值?
不幸的是,您无法使用数组执行此操作。对于非数组变量,该值必须是最终静态的。
答案 4 :(得分:5)
我认为这在Java中可能是不可能的,因为注释及其参数在编译时被解析。
使用Seam 2 http://seamframework.org/,您可以在运行时解析注释参数,表达式语言在双引号内。
在Seam 3中,此功能是模块Seam Solder http://seamframework.org/Seam3/Solder
答案 5 :(得分:0)
您可以使用枚举并在注释字段中引用该枚举