天天看點

Java Reflection(八):注解

内容索引

<a href="http://ifeve.com/java-reflection-8-annotation/#whatarejavaannotation">什麼是注解</a>

<a href="http://ifeve.com/java-reflection-8-annotation/#classannotation">類注解</a>

<a href="http://ifeve.com/java-reflection-8-annotation/#methodannotation">方法注解</a>

<a href="http://ifeve.com/java-reflection-8-annotation/#paramannotation">參數注解</a>

<a href="http://ifeve.com/java-reflection-8-annotation/#fieldannotation">變量注解</a>

利用java反射機制可以在運作期擷取java類的注解資訊。

<a></a>

注解是java 5的一個新特性。注解是插入你代碼中的一種注釋或者說是一種中繼資料(meta data)。這些注解資訊可以在編譯期使用預編譯工具進行處理(pre-compiler tools),也可以在運作期使用java反射機制進行處理。下面是一個類注解的例子:

<code>1</code>

<code>@myannotation</code><code>(name=</code><code>"somename"</code><code>,  value = </code><code>"hello world"</code><code>)</code>

<code>2</code>

<code>public</code> <code>class</code> <code>theclass {</code>

<code>3</code>

<code>}</code>

在theclass類定義的上面有一個@myannotation的注解。注解的定義與接口的定義相似,下面是myannotation注解的定義:

<code>@retention</code><code>(retentionpolicy.runtime)</code>

<code>@target</code><code>(elementtype.type)</code>

<code>4</code>

<code>public</code> <code>@interface</code> <code>myannotation {</code>

<code>5</code>

<code>  </code><code>public</code> <code>string name();</code>

<code>6</code>

<code>  </code><code>public</code> <code>string value();</code>

<code>7</code>

在interface前面的@符号表名這是一個注解,一旦你定義了一個注解之後你就可以将其應用到你的代碼中,就像之前我們的那個例子那樣。

在注解定義中的兩個訓示@retention(retentionpolicy.runtime)和@target(elementtype.type),說明了這個注解該如何使用。

@retention(retentionpolicy.runtime)表示這個注解可以在運作期通過反射通路。如果你沒有在注解定義的時候使用這個訓示那麼這個注解的資訊不會保留到運作期,這樣反射就無法擷取它的資訊。

@target(elementtype.type) 表示這個注解隻能用在類型上面(比如類跟接口)。你同樣可以把type改為field或者method,或者你可以不用這個訓示,這樣的話你的注解在類,方法和變量上就都可以使用了。

你可以在運作期通路類,方法或者變量的注解資訊,下是一個通路類注解的例子:

<code>01</code>

<code>class aclass = theclass.</code><code>class</code><code>;</code>

<code>02</code>

<code>annotation[] annotations = aclass.getannotations();</code>

<code>03</code>

<code>04</code>

<code>for</code><code>(annotation annotation : annotations){</code>

<code>05</code>

<code>    </code><code>if</code><code>(annotation </code><code>instanceof</code> <code>myannotation){</code>

<code>06</code>

<code>        </code><code>myannotation myannotation = (myannotation) annotation;</code>

<code>07</code>

<code>        </code><code>system.out.println(</code><code>"name: "</code> <code>+ myannotation.name());</code>

<code>08</code>

<code>        </code><code>system.out.println(</code><code>"value: "</code> <code>+ myannotation.value());</code>

<code>09</code>

<code>    </code><code>}</code>

<code>10</code>

你還可以像下面這樣指定通路一個類的注解:

<code>annotation annotation = aclass.getannotation(myannotation.</code><code>class</code><code>);</code>

<code>if</code><code>(annotation </code><code>instanceof</code> <code>myannotation){</code>

<code>    </code><code>myannotation myannotation = (myannotation) annotation;</code>

<code>    </code><code>system.out.println(</code><code>"name: "</code> <code>+ myannotation.name());</code>

<code>    </code><code>system.out.println(</code><code>"value: "</code> <code>+ myannotation.value());</code>

<code>8</code>

下面是一個方法注解的例子:

<code>  </code><code>@myannotation</code><code>(name=</code><code>"somename"</code><code>,  value = </code><code>"hello world"</code><code>)</code>

<code>  </code><code>public</code> <code>void</code> <code>dosomething(){}</code>

你可以像這樣通路方法注解:

<code>method method = ... </code><code>//擷取方法對象</code>

<code>annotation[] annotations = method.getdeclaredannotations();</code>

你可以像這樣通路指定的方法注解:

<code>method method = ... </code><code>// 擷取方法對象</code>

<code>annotation annotation = method.getannotation(myannotation.</code><code>class</code><code>);</code>

方法參數也可以添加注解,就像下面這樣:

<code>  </code><code>public</code> <code>static</code> <code>void</code> <code>dosomethingelse(</code>

<code>        </code><code>@myannotation</code><code>(name=</code><code>"aname"</code><code>, value=</code><code>"avalue"</code><code>) string parameter){</code>

<code>  </code><code>}</code>

你可以通過method對象來通路方法參數注解:

<code>annotation[][] parameterannotations = method.getparameterannotations();</code>

<code>class[] parametertypes = method.getparametertypes();</code>

<code>int</code> <code>i=</code><code>0</code><code>;</code>

<code>for</code><code>(annotation[] annotations : parameterannotations){</code>

<code>  </code><code>class parametertype = parametertypes[i++];</code>

<code>  </code><code>for</code><code>(annotation annotation : annotations){</code>

<code>11</code>

<code>12</code>

<code>        </code><code>system.out.println(</code><code>"param: "</code> <code>+ parametertype.getname());</code>

<code>13</code>

<code>        </code><code>system.out.println(</code><code>"name : "</code> <code>+ myannotation.name());</code>

<code>14</code>

<code>15</code>

<code>16</code>

<code>17</code>

需要注意的是method.getparameterannotations()方法傳回一個注解類型的二維數組,每一個方法的參數包含一個注解數組。

下面是一個變量注解的例子:

<code>  </code><code>public</code> <code>string myfield = </code><code>null</code><code>;</code>

你可以像這樣來通路變量的注解:

<code>field field = ... </code><code>//擷取方法對象&lt;/pre&gt;</code>

<code>&lt;pre&gt;annotation[] annotations = field.getdeclaredannotations();</code>

<code> </code><code>if</code><code>(annotation </code><code>instanceof</code> <code>myannotation){</code>

<code> </code><code>myannotation myannotation = (myannotation) annotation;</code>

<code> </code><code>system.out.println(</code><code>"name: "</code> <code>+ myannotation.name());</code>

<code> </code><code>system.out.println(</code><code>"value: "</code> <code>+ myannotation.value());</code>

<code> </code><code>}</code>

你可以像這樣通路指定的變量注解:

<code>field field = ...</code><code>//擷取方法對象&lt;/pre&gt;</code>

<code>&lt;pre&gt;</code>

<code>annotation annotation = field.getannotation(myannotation.</code><code>class</code><code>);</code>

<code>9</code>