原文地址:http://blog.csdn.net/bao19901210/article/details/17201173
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 java.lang.annotation 包中。
1、元注解
元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四种。
1.1、@Retention: 定义注解的保留策略
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
注解类:
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
|
@Retention
(RetentionPolicy.RUNTIME)
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target
({ElementType.FIELD,ElementType.METHOD})
//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Documented
//说明该注解将被包含在javadoc中
public
@interface
FieldMeta {
/**
* 是否为序列号
* @return
*/
boolean
id()
default
false
;
/**
* 字段名称
* @return
*/
String name()
default
""
;
/**
* 是否可编辑
* @return
*/
boolean
editable()
default
true
;
/**
* 是否在列表中显示
* @return
*/
boolean
summary()
default
true
;
/**
* 字段描述
* @return
*/
String description()
default
""
;
/**
* 排序字段
* @return
*/
int
order()
default
0
;
}
|
实体类:
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
Anno {
@FieldMeta
(id=
true
,name=
"序列号"
,order=
1
)
private
int
id;
@FieldMeta
(name=
"姓名"
,order=
3
)
private
String name;
@FieldMeta
(name=
"年龄"
,order=
2
)
private
int
age;
@FieldMeta
(description=
"描述"
,order=
4
)
public
String desc(){
return
"java反射获取annotation的测试"
;
}
public
int
getId() {
return
id;
}
public
void
setId(
int
id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
int
getAge() {
return
age;
}
public
void
setAge(
int
age) {
this
.age = age;
}
}
|
获取到注解的帮助类
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
47
48
49
50
51
52
53
54
55
|
public
class
SortableField {
public
SortableField(){}
public
SortableField(FieldMeta meta, Field field) {
super
();
this
.meta = meta;
this
.field = field;
this
.name=field.getName();
this
.type=field.getType();
}
public
SortableField(FieldMeta meta, String name, Class<?> type) {
super
();
this
.meta = meta;
this
.name = name;
this
.type = type;
}
private
FieldMeta meta;
private
Field field;
private
String name;
private
Class<?> type;
public
FieldMeta getMeta() {
return
meta;
}
public
void
setMeta(FieldMeta meta) {
this
.meta = meta;
}
public
Field getField() {
return
field;
}
public
void
setField(Field field) {
this
.field = field;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
Class<?> getType() {
return
type;
}
public
void
setType(Class<?> type) {
this
.type = type;
}
}
|
运行时获取注解,首先创建一个基类:
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
public
class
Parent<T> {
private
Class<T> entity;
public
Parent() {
init();
}
@SuppressWarnings
(
"unchecked"
)
public
List<SortableField> init(){
List<SortableField> list =
new
ArrayList<SortableField>();
/**getClass().getGenericSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)
* 的直接超类的 Type(Class<T>泛型中的类型),然后将其转换ParameterizedType。。
* getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
* [0]就是这个数组中第一个了。。
* 简而言之就是获得超类的泛型参数的实际类型。。*/
entity = (Class<T>)((ParameterizedType)
this
.getClass().getGenericSuperclass())
.getActualTypeArguments()[
0
];
// FieldMeta filed = entity.getAnnotation(FieldMeta.class);
if
(
this
.entity!=
null
){
/**返回类中所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段
* entity.getFields();只返回对象所表示的类或接口的所有可访问公共字段
* 在class中getDeclared**()方法返回的都是所有访问权限的字段、方法等;
* 可看API
* */
Field[] fields = entity.getDeclaredFields();
//
for
(Field f : fields){
//获取字段中包含fieldMeta的注解
FieldMeta meta = f.getAnnotation(FieldMeta.
class
);
if
(meta!=
null
){
SortableField sf =
new
SortableField(meta, f);
list.add(sf);
}
}
//返回对象所表示的类或接口的所有可访问公共方法
Method[] methods = entity.getMethods();
for
(Method m:methods){
FieldMeta meta = m.getAnnotation(FieldMeta.
class
);
if
(meta!=
null
){
SortableField sf =
new
SortableField(meta,m.getName(),m.getReturnType());
list.add(sf);
}
}
//这种方法是新建FieldSortCom类实现Comparator接口,来重写compare方法实现排序
// Collections.sort(list, new FieldSortCom());
Collections.sort(list,
new
Comparator<SortableField>() {
@Override
public
int
compare(SortableField s1,SortableField s2) {
return
s1.getMeta().order()-s2.getMeta().order();
// return s1.getName().compareTo(s2.getName());//也可以用compare来比较
}
});
}
return
list;
}
}
|
创建子类继承基类:
1
2
3
|
public
class
Child
extends
Parent<Anno>{
}
|
测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
class
TestAnnotation {
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
public
static
void
main(String[] args) {
Parent c =
new
Child();
List<SortableField> list = c.init();
//获取泛型中类里面的注解
//输出结果
for
(SortableField l : list){
System.out.println(
"字段名称:"
+l.getName()+
"\t字段类型:"
+l.getType()+
"\t注解名称:"
+l.getMeta().name()+
"\t注解描述:"
+l.getMeta().description());
}
}
}
|