java-如何在注釋中使用數組常量

我想使用常量作為注釋值。

interface Client {
    @Retention(RUNTIME)
    @Target(METHOD)
    @interface SomeAnnotation { String[] values(); }
    interface Info {
        String A = "a";
        String B = "b";
        String[] AB = new String[] { A, B };
    }
    @SomeAnnotation(values = { Info.A, Info.B })
    void works();
    @SomeAnnotation(values = Info.AB)
    void doesNotWork();
}

常量Info.AInfo.B可以在注釋中使用,但不能在數組Info.AB中使用,因為在該位置它必須是數組初始值設定項。 注釋值僅限于可以內聯到類的字節碼中的值。 這對于數組常量是不可能的,因為必須在加載Info時構造它。 是否有解決此問題的方法?

asked 2020-02-29T11:02:17Z
6個解決方案
45 votes

不,沒有解決方法。

answered 2020-02-29T11:02:25Z
14 votes

為什么不將注釋值設為枚舉,它們是所需的實際數據值的鍵?

歲月

enum InfoKeys
{
 A("a"),
 B("b"),
 AB(new String[] { "a", "b" }),
 InfoKeys(Object data) { this.data = data; }
 private Object data;
}
@SomeAnnotation (values = InfoKeys.AB)

可以為類型安全性進行改進,但是您明白了。

answered 2020-02-29T11:02:54Z
2 votes

盡管無法直接將數組作為注釋參數值傳遞,但是有一種方法可以有效地獲得類似的行為(取決于您計劃使用注釋的方式,這可能不適用于每種用例)。

這是一個示例-假設我們有一個InternetServer類,它具有hostname屬性。 我們想使用常規的Java驗證來確保沒有對象具有“保留的”主機名。 我們可以(某種程度上)將保留的主機名數組傳遞給處理主機名驗證的注釋。

請注意,使用Java驗證時,使用“有效載荷”傳遞此類數據會更加習慣。 我希望該示例更具通用性,因此我使用了自定義接口類。

// InternetServer.java -- an example class that passes an array as an annotation value
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.Pattern;
public class InternetServer {
   
answered 2020-02-29T11:03:24Z
1 votes

這是因為可以在運行時更改數組的元素(Info.AB),而注釋值在編譯后仍保持不變。

考慮到這一點,當人們嘗試更改2768853331698254254848的元素并期望注解的值發生變化時可以领救济金的游戏,不可避免地會感到困惑(不會)。 而且,如果允許注釋值在運行時更改,則它將不同于編譯時使用的注釋值。 想象一下混亂吧!

(這里的混亂意味著有人可能會發現一個錯誤,并花費數小時進行調試。)

answered 2020-02-29T11:03:53Z
0 votes

正如先前的文章中已經提到的那樣,注釋值是編譯時常量,無法使用數組值作為參數。

我以不同的方式解決了這個問題。

如果您擁有處理邏輯,請利用它。

例如,為注釋添加一個附加參數:

@Retention(RUNTIME)
@Target(METHOD)
@interface SomeAnnotation { 
    String[] values();
    boolean defaultInit() default false;
}

使用此參數:

@SomeAnnotation(defaultInit = true)
void willWork();

這將是AnnotationProcessor的標記,該標記可以執行任何操作-使用數組對其進行初始化,使用27688538270120022002或使用Enums(例如Enum.values())并將它們映射到String[]

希望這將指導有類似情況的人朝正確的方向發展。

answered 2020-02-29T11:04:40Z
-1 votes
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Handler {
    enum MessageType { MESSAGE, OBJECT };
    String value() default "";
    MessageType type() default MessageType.MESSAGE;
}
answered 2020-02-29T11:04:55Z
translate from