什麼是JAVA註解?這是百度百科的解釋:
定義:註解(Annotation),也叫元數據。一種代碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,註釋。
作用分類:
①編寫文檔:通過代碼裏標識的元數據生成文檔【生成文檔doc文檔】
②代碼分析:通過代碼裏標識的元數據對代碼進行分析【使用反射】
③編譯檢查:通過代碼裏標識的元數據讓編譯器能夠實現基本的編譯檢查【Override】
寫過JAVA代碼的人對註解都不陌生,尤其在各種框架中很常見。這些註解都非常優秀,也很容易理解,但是,爲什麼要使用註解?註解是如何工作的?讓我自定義一個註解來解釋,相信理解了這個示例以後。
首先我們分析一個很簡單的場景,我們有一個叫Person的POJO類,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public
class
Person { private
String name; private
String age; public
String getName() { return
name; } public
void
setName(String name) { this .name
= name; } public
String getAge() { return
age; } public
void
setAge(String age) { this .age
= age; } @Override public
String toString() { return
"Person [name="
+ name + ",
age="
+ age + "]" ; } }
|
然後有這樣一個HashMap:
1
2
3
4
5
|
private
static
Map input = new
HashMap(); static
{ input.put( "name" ,
"Boaz" ); input.put( "age" ,
"29" ); }
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public
class
Main { private
static
Map input = new
HashMap(); static
{ input.put( "name" ,
"Boaz" ); input.put( "age" ,
"29" ); } public
static
void
main(String[] args) { Person
person = Map2Pojo(input, Person. class ); System.out.print(person); } private
static
<T> T Map2Pojo(Map input, Class<T> clazz) { Method[]
methods = clazz.getMethods(); T
t; try
{ t
= clazz.newInstance(); }
catch
(Exception e) { e.printStackTrace(); return
null ; } for
(Method method : methods) { input.keySet().forEach((key)
-> { if
(( "set"
+ key).equals(method.getName().toLowerCase())) { try
{ method.invoke(t,
input.get(key)); }
catch
(Exception e) { e.printStackTrace(); return ; } } }); } return
t; } }
|
1
2
3
4
5
6
|
private
static
Map input = new
HashMap(); static
{ input.put( "Name" ,
"Boaz" ); input.put( "Age" ,
"29" ); }
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
class
Person { private
String name; private
String age; public
String getName() { return
name; } @MapKey (KeyName
= "Name" ) public
void
setName(String name) { this .name
= name; } public
String getAge() { return
age; } @MapKey (KeyName
= "Age" ) public
void
setAge(String age) { this .age
= age; } @Override public
String toString() { return
"Person [name="
+ name + ",
age="
+ age + "]" ; } } |
1
2
3
4
5
|
@Target (ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) public
@interface
MapKey { String
KeyName() default
"" ; } |
@Target
(ElementType.METHOD)
和@Retention
(RetentionPolicy.RUNTIME)
兩個註解,這兩個註解被稱爲"修飾註解的註解",從字面是就可以理解,@Target
(ElementType.METHOD)
表示說明該註解只能註解方法,@Retention
(RetentionPolicy.RUNTIME)
表示@MapKey
(KeyName
=
"Name"
),這裏也賦予了一個默認值爲空字符串
註解定義和使用後,我們對Map2Pojo工具類稍作修改,修改後完整源碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
public
class
Main { private
static
Map<String, String> input = new
HashMap<String, String>(); static
{ input.put( "Name" ,
"Boaz" ); input.put( "Age" ,
"29" ); } public
static
void
main(String[] args) { Person
person = Map2Pojo(input, Person. class ); System.out.print(person); } private
static
<T> T Map2Pojo(Map input, Class<T> clazz) { Method[]
methods = clazz.getMethods(); T
t; try
{ t
= clazz.newInstance(); }
catch
(Exception e) { e.printStackTrace(); return
null ; } for
(Method method : methods) { input.keySet().forEach((key)
-> { if
(method.getAnnotations().length == 1 )
{ MapKey
mapKey = (MapKey) method.getAnnotations()[ 0 ]; String
realKey = mapKey.KeyName(); if
(key.equals(realKey)) { try
{ method.invoke(t,
input.get(key)); }
catch
(Exception e) { e.printStackTrace(); return ; } } } if
(( "set"
+ key).equals(method.getName().toLowerCase())) { try
{ method.invoke(t,
input.get(key)); }
catch
(Exception e) { e.printStackTrace(); return ; } } }); } return
t; } } |
修改的部分在22-33行,這裏就讀取了每個Method的註解MapKey,然後獲取註解MapKey中的KeyName值來同Map中的key值進行映射。
這個示例中的註解爲運行時註解,大多數自定義註解都是運行時註解。從我的角度來理解,註解可以算做是一種增加重用的機制,在這個示例中,新增了一個註解,Person類就可以在改變註解值的情況下適配不同的Map的Key值!