2013-05-26 41 views
6

Java註釋順序在運行時是否持久?我檢查了OpenJDK 1.7.0_21 - 它保留了註釋順序。我可以期待所有Java VM上的持久性嗎?Java註釋順序是否持久?

+2

我很好奇:怎麼會是怎麼回事? – acdcjunior

+0

我想知道,如果我可以使用額外的註釋較早的註解指定額外的參數(如@DoSomething( 「F1」)@Arg( 「ARG1」)@Arg( 「ARG2」)@DoSomething( 「F2」)@ Arg(「arg2.1」)@Arg(「arg2.2」)) – Azazar

+0

我不會這麼做......看起來很混亂。普通的'@DoSomething(value =「f1」,a1 =「arg1」,a2 =「arg2」)有什麼問題; @DoSomething(value =「f2」,a1 =「arg2.1」,a2 =「arg2.2」);'? – acdcjunior

回答

4

取決於你的意思是「持久性」。我認爲你可能意味着問題中隱含的意思,所以這裏有幾個問:答:

註釋順序是否持久?
是的,它被寫入.class文件中的順序不變。

是否在.class文件註釋爲了反映源代碼註釋訂單?
是的。如果您編譯代碼...

@Column(length = 256) 
@NotBlankConstraint(message = "The application title must be set.") 
@Size(min = 1, max = 256, message = "The application title must be set and not longer than 250 characters.") 
private String title; 

javap -v檢查:

#67 = Utf8    Ljavax/validation/constraints/Size; 
... 
private java.lang.String title; 
    descriptor: Ljava/lang/String; 
    flags: ACC_PRIVATE 
    RuntimeVisibleAnnotations: 
    0: #50(#62=I#63) 
    1: #64(#65=s#66) 
    2: #67(#68=I#69,#70=I#63,#65=s#71 

如果更改註釋的順序,在字節代碼的順序也將改變。使用OpenJDK 1.8.0_121進行測試,但我認爲早期的JDK也是如此。

是否由getAnnotations()方法保存的字節碼的順序?
是的,從我所看到的情況來看,它始終返回與.class文件中字節代碼相同的順序。

getAnnotations()保證,以反映未來的字節碼註釋訂單?
不可以。正如其他答案所回答的那樣,此行爲未記錄在案,因此不能依賴於公共庫。
但是,有一些subtle signs that the order should be kept莫名其妙。

現在爲您的目的, 如果有保證,我是否應該使用該命令將某些註釋應用於某些以前的註釋?
這是一個有趣的問題,但我會說大多數Java程序員不會喜歡這樣的。這不會是很直觀和可讀的代碼。我會建議組註釋,比如像

@ValidationGroup(
    validators = { @NotNull, @NotEmpty }, 
    message = "User name must be filled." 
) 
public String getUsername(); 

這裏的問題是,你不能有「任何註釋」的數組,因爲沒有繼承了註解,這不能做( Java 1.8)。因此,各種框架訴諸於Bean Validation使用什麼 - 請參閱它的組的概念。

最後,我第二次到Eric的評論檢查JSR 303,它的相當出色,並且還融入像RestEasy的許多其他庫。

+0

部分看起來並不可能:'驗證= {@NotNull,@NotEmpty}'這是一個疏忽,或者您也可以提供'驗證的定義()'成員,允許這種用法嗎? –

+0

@GlennLane,你是對的。我會用更好的例子來解決。 –

1

java.lang.reflect.AnnotatedElement.getAnnotations() API說它返回此元素上存在的所有註釋。它沒有說明返回這些註釋的順序

+1

結帳這樣的回答重複的:http://stackoverflow.com/a/30222541/810109 - 關於它的註解以**有保證的**順序檢索。 – mkurz

-4

在Java 7及更低版本中,不能在元素上包含多個相同類型的註釋。您可以將它們作爲另一個註釋的值的一部分:

// JSR 303 
@Pattern.List({ 
    @Pattern(regexp="\\w{8,14}"), 
    @Pattern(regexp=".*Z.*") 
}) 
public String getCode() { 
    return code; 
} 

Java 8將放寬這一點。見Oracle's bug tracker。這在Stack Overflow討論。

+1

這並沒有回答訂單是否重要的​​問題。如果你有'public void method(@Foo @Bar String str)',假設我將它設置爲處理它符合foo的所有條件的條形將會很好。你的榜樣的 – corsiKa