❶ 通過註解和反射實現一個簡單的@Value註解
java註解(Annotation)就是一種java標注,並且能夠攜帶數據, 是在JDK5.0被引入的。
Java的註解可以標注Java語言中的類、變數、方法、參數、包等等。
值得注意的是: 上面所說的Java註解只是一種標注,所以註解需要配合反射來使用才能發揮出強大作用。
註解的成員變數只支持 八種基本數據類型(byte、short、int、long、float、double、char、boolean)、String、Class、Enum、Annotation 。
還有的就是,所有的註解余坦都是Annotation介面的實現類,可以把Annotation介面看成是所有註解的超類 。
上面就是定義了一個可以標注在類或者註解以及方法上的,保留到運行期的註解。 但是也僅僅是定義了一個註解而已,一個註解要發揮它自己的作用,還需要反射的配合。
反射是java中的一種機制,通過這種機制我們能夠在運行時獲取到一個類的一切信息(繼承的類、實現的介面、屬性、方法等), 以及註解信息和註解所攜豎山桐帶的數據 。
通過獲取到的類信息,我唯哪們可以構造一個新的對象、獲取到某個對象的屬性值、執行某個對象的方法等。
定義value註解
定義pojo User類
測試並使用註解
❷ JAVA自定義註解:能否通過反射找到哪一個類加了該註解(在一個項目范圍內)
當然可以;
首先,你得獲得自定義類所對應的Class對象,
其次,通過Class對象獲得所對應的所有方法,建立一顫讓個Method[] list 。
然後,慶握遍歷該Method[] list 數組,取得每一個Method對象,調用該對象的isAnnotationPresent()方法。判斷該方法是否被你所標記的Annotation修飾。
最後,如果該方法返回true,自然就是那你要找的方法,否則,false。
祝你好運!!最好就是自己找到API文檔,進行查閱相關類譽洞慶,以及相關方法的說明,自己編寫代碼,這樣你會學會很多的,祝你成功!!!!
❸ java獲取註解的值
很多御如察朋友都想知道java怎麼獲取註解的值?下面就一起來了解一下吧~
1、定義一個註解,用於給全局變數field欄位賦值
package com.haha.study.annotation.value; 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; /** * description: 定義一個註解,用於給 全局變數 field 欄位 賦值,並使用反射取值。
* 特別提醒: @Rentention(RetentionPolicy.RUNTIME) 時,註解才會被jvm載入,才能使用反射獲取。 * @version v1.0 * @author w * @date 2018年8月1日下午2:37:40 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(value=ElementType.FIELD) public @interface Fields { int sort() default 0 ; String value() ; }
2、創建一個普通的類,使用 @ConsAnnotation、@Fields 註解
package com.haha.study.annotation.value; /** * description: 創建一個普通的類,使用 @ConsAnnotation、@Fields 註解。 * @version 鎮茄v1.0 * @author w * @date 2018年8月1日下午2:50:23 */ @ConsAnnotation(request = { "hello","world","annotation!" }) public class User { @Fields("中華人民共和國") private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
3、針對 com.haha.study.annotation.value.User 類使用註解的測試
package com.haha.study.annotation.value; import java.lang.reflect.Field; import java.util.Arrays; /** * description: 針對 com.haha.study.annotation.value.User 類使橡咐用註解的測試 * @version v1.0 * @author w * @date 2018年8月1日下午2:37:13 */ public class ValueTest { public static void main(String[] args) throws Exception { User user = new User(); // 1、 獲取 User類上的註解 @ConsAnnotation ConsAnnotation anno = user.getClass().getAnnotation(ConsAnnotation.class); String[] arr = anno.request(); System.out.println(Arrays.toString(arr)); // [hello, world, annotation!] // 2、 獲取User類中 private String userName; 變數上的註解 @Field Field f = user.getClass().getDeclaredField("userName"); Fields anno2 = f.getAnnotation(Fields.class); user.setUserName(anno2.value()); System.out.println(user.getUserName()); // 中華人民共和國 } }
❹ java反射無法動態獲取註解
@Action
public void test() throws NoSuchMethodException, SecurityException{
StackTraceElement[] stack = new Throwable().getStackTrace();
Method method = this.getClass().getMethod(stack[0].getMethodName());
for(Annotation an : method.getAnnotations()){
System.out.println(an);
}
}
也可以寫個公共方法來獲取,stack[0]這里要改成stack[1]
❺ java反射一定要和註解一起使用嗎
不是一定,看你要做什麼,配合註解使用可以更加靈活。比如你做個動態代理,需要用註解嗎?當然不需要。前悉再比如說像spring的自動裝配,我們可以指定它的掃描的路徑,但是這個指定的路徑下的bean都需要慧返乎自動裝配嗎?答世燃案是否定的,那怎麼辦?這個時候就需要註解了,通過註解讓開發人員自己決定哪些需要容器管理哪些不需要,不知道你是否已經接觸過spring。但是總結下來就是反射是不一定要和註解一起使用的。
❻ java反射機制 怎樣獲取到類上面的註解
//定義註解並指定java註解保留策略為運行時RUNTIME,運行時注入到JAVA位元組碼文件里
//這樣才可以在運行時反射並獲取它。
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@interfaceMyAnnotation{
Stringkey()default"";
intvalue()default0;
}
//使用註解
@MyAnnotation(key="key1",value=200)
classMyClass{}
//反射註解
publicstaticvoidmain(String[]args){
MyClassmyClass=newMyClass();
MyAnnotationannotation=myClass.getClass().getAnnotation(MyAnnotation.class);
System.out.println("key="+annotation.key()+" value="+annotation.value());
}
❼ java註解是怎麼實現的
註解的使用一般是與java的反射一起使用,下面是一個例子
註解相當於一種標記,在程序中加了註解就等於為程序打上了某種標記,沒加,則等於沒有某種標記,以後,javac編譯器,開發工具和其他程序可以用反射來了解你的類及各種元素上有無何種標記,看你有什麼標記,就去干相應的事。標記可以加在包,類,欄位,方法,方法的參數以及局部變數上。
自定義註解及其應用
1)、定義一個最簡單的註解
public @interface MyAnnotation {
//......
}
2)、把註解加在某個類上:
@MyAnnotation
public class AnnotationTest{
//......
}
以下為模擬案例
自定義註解@MyAnnotation
1 package com.ljq.test;
2
3 import java.lang.annotation.ElementType;
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.annotation.Target;
7
8 /**
9 * 定義一個註解
10 *
11 *
12 * @author jiqinlin
13 *
14 */
15 //Java中提供了四種元註解,專門負責註解其他的註解,分別如下
16
17 //@Retention元註解,表示需要在什麼級別保存該注釋信息(生命周期)。可選的RetentionPoicy參數包括:
18 //RetentionPolicy.SOURCE: 停留在java源文件,編譯器被丟掉
19 //RetentionPolicy.CLASS:停留在class文件中,但會被VM丟棄(默認)
20 //RetentionPolicy.RUNTIME:內存中的位元組碼,VM將在運行時也保留註解,因此可以通過反射機制讀取註解的信息
21
22 //@Target元註解,默認值為任何元素,表示該註解用於什麼地方。可用的ElementType參數包括
23 //ElementType.CONSTRUCTOR: 構造器聲明
24 //ElementType.FIELD: 成員變數、對象、屬性(包括enum實例)
25 //ElementType.LOCAL_VARIABLE: 局部變數聲明
26 //ElementType.METHOD: 方法聲明
27 //ElementType.PACKAGE: 包聲明
28 //ElementType.PARAMETER: 參數聲明
29 //ElementType.TYPE: 類、介面(包括註解類型)或enum聲明
30
31 //@Documented將註解包含在JavaDoc中
32
33 //@Inheried允許子類繼承父類中的註解
34
35
36 @Retention(RetentionPolicy.RUNTIME)
37 @Target({ElementType.METHOD, ElementType.TYPE})
38 public @interface MyAnnotation {
39 //為註解添加屬性
40 String color();
41 String value() default "我是林計欽"; //為屬性提供默認值
42 int[] array() default {1, 2, 3};
43 Gender gender() default Gender.MAN; //添加一個枚舉
44 MetaAnnotation metaAnnotation() default @MetaAnnotation(birthday="我的出身日期為1988-2-18");
45 //添加枚舉屬性
46
47 }
註解測試類AnnotationTest
1 package com.ljq.test;
2
3 /**
4 * 註解測試類
5 *
6 *
7 * @author jiqinlin
8 *
9 */
10 //調用註解並賦值
11 @MyAnnotation(metaAnnotation=@MetaAnnotation(birthday = "我的出身日期為1988-2-18"),color="red", array={23, 26})
12 public class AnnotationTest {
13
14 public static void main(String[] args) {
15 //檢查類AnnotationTest是否含有@MyAnnotation註解
16 if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
17 //若存在就獲取註解
18 MyAnnotation annotation=(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
19 System.out.println(annotation);
20 //獲取註解屬性
21 System.out.println(annotation.color());
22 System.out.println(annotation.value());
23 //數組
24 int[] arrs=annotation.array();
25 for(int arr:arrs){
26 System.out.println(arr);
27 }
28 //枚舉
29 Gender gender=annotation.gender();
30 System.out.println("性別為:"+gender);
31 //獲取註解屬性
32 MetaAnnotation meta=annotation.metaAnnotation();
33 System.out.println(meta.birthday());
34 }
35 }
36 }
枚舉類Gender,模擬註解中添加枚舉屬性
1 package com.ljq.test;
2 /**
3 * 枚舉,模擬註解中添加枚舉屬性
4 *
5 * @author jiqinlin
6 *
7 */
8 public enum Gender {
9 MAN{
10 public String getName(){return "男";}
11 },
12 WOMEN{
13 public String getName(){return "女";}
14 }; //記得有「;」
15 public abstract String getName();
16 }
註解類MetaAnnotation,模擬註解中添加註解屬性
1 package com.ljq.test;
2
3 /**
4 * 定義一個註解,模擬註解中添加註解屬性
5 *
6 * @author jiqinlin
7 *
8 */
9 public @interface MetaAnnotation {
10 String birthday();
11 }
❽ java開發中常用的註解有哪些
Java 註解全面解析,學習java做一個java工程師不但待遇高,而且前途無可限量。為什麼這樣說呢?因為java程序語言作為最流行的計算機開發語言之一,幾乎所有的系統、軟體、app、網頁等都是需要用到java的。
1.基本語法
註解定義看起來很像介面的定義。事實上,與其他任何介面一樣,註解也將會編譯成class文件。
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {}
除了@符號以外,@Test的定義很像一個空的介面。定義註解時,需要一些元註解(meta-annotation),如@Target和@Retention
@Target用來定義註解將應用於什麼地方(如一個方法或者一個域)
@Retention用來定義註解在哪一個級別可用,在源代碼中(source),類文件中(class)或者運行時(runtime)
在註解中,一般都會包含一些元素以表示某些值。當分析處理註解時,程序可以利用這些值。沒有元素的註解稱為標記註解(marker annotation)
四種元註解,元註解專職負責註解其他的註解,所以這四種註解的Target值都是ElementType.ANNOTATION_TYPE
註解 說明
@Target 表示該註解可以用在什麼地方,由ElementType枚舉定義
CONSTRUCTOR:構造器的聲明
FIELD:域聲明(包括enum實例)
LOCAL_VARIABLE:局部變數聲明
METHOD:方法聲明
PACKAGE:包聲明
PARAMETER:參數聲明
TYPE:類、介面(包括註解類型)或enum聲明
ANNOTATION_TYPE:註解聲明(應用於另一個註解上)
TYPE_PARAMETER:類型參數聲明(1.8新加入)
TYPE_USE:類型使用聲明(1.8新加入)
PS:當註解未指定Target值時,此註解可以使用任何元素之上,就是上面的類型
@Retention 表示需要在什麼級別保存該註解信息,由RetentionPolicy枚舉定義
SOURCE:註解將被編譯器丟棄(該類型的註解信息只會保留在源碼里,源碼經過編譯後,註解信息會被丟棄,不會保留在編譯好的class文件里)
CLASS:註解在class文件中可用,但會被VM丟棄(該類型的註解信息會保留在源碼里和class文件里,在執行的時候,不會載入到虛擬機(JVM)中)
RUNTIME:VM將在運行期也保留註解信息,因此可以通過反射機制讀取註解的信息(源碼、class文件和執行的時候都有註解的信息)
PS:當註解未定義Retention值時,默認值是CLASS
@Documented 表示註解會被包含在javaapi文檔中
@Inherited 允許子類繼承父類的註解
2. 註解元素
– 註解元素可用的類型如下:
– 所有基本類型(int,float,boolean,byte,double,char,long,short)
– String
– Class
– enum
– Annotation
– 以上類型的數組
如果使用了其他類型,那編譯器就會報錯。也不允許使用任何包裝類型。註解也可以作為元素的類型,也就是註解可以嵌套。
元素的修飾符,只能用public或default。
– 默認值限制
編譯器對元素的默認值有些過分挑剔。首先,元素不能有不確定的值。也就是說,元素必須要麼具有默認值,要麼在使用註解時提供元素的值。
其次,對於非基本類型的元素,無論是在源代碼中聲明,還是在註解介面中定義默認值,都不能以null作為值。這就是限制,這就造成處理器很難表現一個元素的存在或缺失狀態,因為每個註解的聲明中,所有的元素都存在,並且都具有相應的值。為了繞開這個限制,只能定義一些特殊的值,例如空字元串或負數,表示某個元素不存在。
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface MockNull {
public int id() default -1;
public String description() default 「」;
}
3. 快捷方式
何為快捷方式呢?先來看下springMVC中的Controller註解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
String value() default 「」;
}
可以看見Target應用於類、介面、註解和枚舉上,Retention策略為RUNTIME運行時期,有一個String類型的value元素。平常使用的時候基本都是這樣的:
@Controller(「/your/path」)
public class MockController { }
這就是快捷方式,省略了名-值對的這種語法。下面給出詳細解釋:
註解中定義了名為value的元素,並且在應用該註解的時候,如果該元素是唯一需要賦值的一個元素,那麼此時無需使用名-值對的這種語法,而只需在括弧內給出value元素所需的值即可。這可以應用於任何合法類型的元素,當然了,這限制了元素名必須為value。
4. JDK1.8註解增強
TYPE_PARAMETER和TYPE_USE
在JDK1.8中ElementType多了兩個枚舉成員,TYPE_PARAMETER和TYPE_USE,他們都是用來限定哪個類型可以進行註解。舉例來說,如果想要對泛型的類型參數進行註解:
public class AnnotationTypeParameter<@TestTypeParam T> {}
那麼,在定義@TestTypeParam時,必須在@Target設置ElementType.TYPE_PARAMETER,表示這個註解可以用來標注類型參數。例如:
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestTypeParam {}
ElementType.TYPE_USE用於標注各種類型,因此上面的例子也可以將TYPE_PARAMETER改為TYPE_USE,一個註解被設置為TYPE_USE,只要是類型名稱,都可以進行註解。例如有如下註解定義:
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {}
那麼以下的使用註解都是可以的:
List<@Test Comparable> list1 = new ArrayList<>();
List<? extends Comparable> list2 = new ArrayList<@Test Comparable>();
@Test String text;
text = (@Test String)new Object();
java.util. @Test Scanner console;
console = new java.util.@Test Scanner(System.in);
PS:以上@Test註解都是在類型的右邊,要注意區分1.8之前的枚舉成員,例如:
@Test java.lang.String text;
在上面這個例子中,顯然是在進行text變數標注,所以還使用當前的@Target會編譯錯誤,應該加上ElementType.LOCAL_VARIABLE。
@Repeatable註解
@Repeatable註解是JDK1.8新加入的,從名字意思就可以大概猜出他的意思(可重復的)。可以在同一個位置重復相同的註解。舉例:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Filter {
String [] value();
}
如下進行註解使用:
@Filter({「/admin」,」/main」})
public class MainFilter { }
換一種風格:
@Filter(「/admin」)
@Filter(「/main」)
public class MainFilter {}
在JDK1.8還沒出現之前,沒有辦法到達這種「風格」,使用1.8,可以如下定義@Filter:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Filters.class)
public @interface Filter {
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Filters {
Filter [] value();
}
實際上這是編譯器的優化,使用@Repeatable時告訴編譯器,使用@Filters來作為收集重復註解的容器,而每個@Filter存儲各自指定的字元串值。
JDK1.8在AnnotatedElement介面新增了getDeclaredAnnotationsByType和getAnnotationsByType,在指定@Repeatable的註解時,會尋找重復註解的容器中。相對於,getDeclaredAnnotation和getAnnotation就不會處理@Repeatable註解。舉例如下:
@Filter(「/admin」)
@Filter(「/filter」)
public class FilterClass {
public static void main(String[] args) {
Class<FilterClass> filterClassClass = FilterClass.class;
Filter[] annotationsByType = filterClassClass.getAnnotationsByType(Filter.class);
if (annotationsByType != null) {
for (Filter filter : annotationsByType) {
System.out.println(filter.value());
}
}
System.out.println(filterClassClass.getAnnotation(Filter.class));
}
}
日誌如下:
/admin
/filter
null
望採納!
❾ Java 註解的讀取註解信息的方法
屬於重點,在系統中用到註解許可權時非常有用,可以精確控制許可權的粒度
注意:要想使用反射去讀取註解,必須將Retention的值選為Runtime Java代碼importjava.lang.annotation.Annotation;importjava.lang.reflect.Method;//讀取註解信息{publicstaticvoidmain(String[]args)throwsException{//測試AnnotationTest類,得到此類的類對象Classc=Class.forName(com.iwtxokhtd.annotation.AnnotationTest);//獲取該類所有聲明的方法Method[]methods=c.getDeclaredMethods();//聲明註解集合Annotation[]annotations;//遍歷所有的方法得到各方法上面的註解信息for(Methodmethod:methods){//獲取每個方法上面所聲明的所有註解信息annotations=method.getDeclaredAnnotations();//再遍歷所有的註解,列印其基本信息System.out.println(method.getName());for(Annotationan:annotations){System.out.println(方法名為:+method.getName()+其上面的註解為:+an.annotationType().getSimpleName());Method[]meths=an.annotationType().getDeclaredMethods();//遍歷每個註解的所有變數for(Methodmeth:meths){System.out.println(註解的變數名為:+meth.getName());}}}}}
❿ Java 的註解是什麼原理
Annotation(註解)是JDK5.0及以後版本引入的。它可以用於創建文檔,跟蹤代碼中的依賴性,甚至執行基本編譯時檢查。註解是以『@註解名』在代碼中存在的,根據註解參數的個數,我們可以將註解分為:標記註解、單值註解、完整註解三類。它們都不會直接影響到程序的語義,只是作為註解(標識)存在,我們可以通過反射機制編程實現對這些元數據的訪問。另外,你可以在編譯時選擇代碼里的註解是否只存在於源代碼級,或者它也能在class文件中出現。
元數據的作用
如果要對於元數據的作用進行分類,大致可分為三類:
編寫文檔:通過代碼里標識的元數據生成文檔。
代碼分析:通過代碼里標識的元數據對代碼進行分析。
編譯檢查:通過代碼里標識的元數據讓編譯器能實現基本的編譯檢查