ChatGPT解决这个技术问题 Extra ChatGPT

如何从常量 java 为注解提供值

我认为这在 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[] 常量为注释提供值吗?


C
Community

编译常量 can only be primitives and Strings

15.28。常量表达式 编译时常量表达式是表示原始类型值或字符串的表达式,它不会突然完成并且仅使用以下内容组成: 原始类型的文字和字符串类型的文字 转换为原始类型和转换为类型字符串 [...] 运算符 [...] 带括号的表达式,其包含的表达式是常量表达式。引用常量变量的简单名称。 TypeName 形式的限定名称。引用常量变量的标识符。

实际上在java中没有办法保护数组中的项目。在运行时,总是有人可以做 FieldValues.FIELD1[0]="value3",因此如果我们更深入地观察,数组不可能是真正的常数。


@TacB0sS,枚举不是常量表达式。
嗯......也许你应该试一试,让我知道......我一直在使用它们:)
更相关的规范在 Annotations 下。除了常量表达式,注解值可以是数组初始化器类文字枚举常量
啊哈!我用的是长的,不是长的.....解决了我的问题!!!谢谢!!!!!!!!!!!!!!!
@TacB0sS 您可以在注释中使用 enum,但它们不是编译时常量。当您编写 static final EnumType VARIABLE = EnumType.ENUM_CONSTANT; 并尝试在注释中使用 VARIABLE 时,差异会变得很明显;它行不通。您只能使用不是常量表达式的 EnumType.ENUM_CONSTANT,但在注释(和 switch 语句)中特别允许使用。
A
Andrzej Doyle

您可以使用常量(即静态的最终变量)作为注解的参数。作为一个简单的例子,我经常使用这样的东西:

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 数组尝试过这个,并没有遇到你提到的问题 - 但是编译器 did 告诉我“属性值必须是常量”,尽管数组是定义为 public static final String[]。也许它不喜欢数组是可变的这一事实?唔...


我真倒霉!哦,是的,我能够传递字符串/数字,但不能传递数组。我会在这上面多花点时间,如果没有任何结果,我会接受答案:)
是的,我的猜测是 FIELD1 数组的可变性是这里的问题。您可以使用数组初始值设定项来声明数组,因为没有其他东西可以访问该数组,因此以后不能更改它。
这解决了我的问题。只需要在注解和代码之间共享一个字符串常量。谢谢!
静态最终变量不是唯一的先决条件。如果您尝试动态计算变量,您将收到相同的错误消息。
l
lue

在您的示例中,您没有为它提供数组。以下编译良好:

public @interface SampleAnnotation {
    String[] sampleValues();
}

public class Values {
    public static final String val0 = "A";
    public static final String val1 = "B";

    @SampleAnnotation(sampleValues={ val0, val1 })
    public void foo() {
    }
}

它在示例中提供了一个数组,而不是直接在注释声明中创建的数组。
K
Kevin

有人知道我如何使用 String 常量或 String[] 常量为注释提供值吗?

不幸的是,你不能用数组来做到这一点。对于非数组变量,值必须是最终静态的。


它必须是最终的,但不必是静态的。
l
lue

我认为这在 Java 中可能是不可能的,因为注释及其参数是在编译时解析的。

使用 Seam 2 http://seamframework.org/,您可以在运行时解析注释参数,并在双引号内使用表达式语言。

在 Seam 3 http://seamframework.org/Seam3/Solder 中,此功能是模块 Seam Solder


不,您没有在运行时解析参数。该参数在编译时解析。然后它们被用来在运行时做某事实际上与它们的值何时设置无关。
K
Kaustubh Thawari

您可以使用枚举并在注释字段中引用该枚举


您应该添加一个示例。