java 1.5开始引入了注解和反射,正确的来说注解是反射的一部分,没有反射,注解无法正常使用,但离开注解,反射依旧可以使用,因此来说,反射的定义应该包含注解才合理一些。
当然,这只是个人想法,至于java官方为什么这么泾渭分明不得而知,最重要的是如何使用注解。
注解的功能分为2部分:
-
作为特定的标记
-
额外信息的载体
>>>>定义一个UserAnnotation注解类
1
2
3
4
5
6
7
8
|
@Target(value = { ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public
@
interface
UserAnnotation {
public
int id()
default
0;
public
String name()
default
""
;
public
int age()
default
18;
public
String gender()
default
"M"
;
}
|
其中@target个@Retention本身就是注解
【@target】这个注解来指定给哪一类java成员注解,指定注解目标该是什么样的东西
注解@Target的源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
//这不是在作弊,这确实是自己注解自己,所以说注解也可以被字节给注解
public
@
interface
Target {
ElementType[] value();
//值可以使数组 value={...}
}
public
enum ElementType {
TYPE,
//给类(型)注解
FIELD,
//给字段注解,不要忘了,字段可以是对象
METHOD,
//给方法注解
PARAMETER,
//给参数注解
CONSTRUCTOR,
//给构造方法注解
LOCAL_VARIABLE,
//给局部变量注解
ANNOTATION_TYPE,
//给注解注解(这貌似把自己不当类来看)
PACKAGE,
//给包注解
TYPE_PARAMETER,
//不知道,等知道了我再写在这里
TYPE_USE
//这个也不知道
}
|
【@Retention】表示注解运行的状态,换句话说,注解改在什么样的状态下才能运行
注解@Retention的源码
1
2
3
4
5
6
7
8
9
10
11
12
|
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public
@
interface
Retention {
RetentionPolicy value();
}
public
enum RetentionPolicy {
SOURCE,
//源码状态运行,
CLASS,
//编译类文件时运行
RUNTIME
//运行时运行
}
|
一般来说,源码状态运行和编译状态运行的注解往往和编译器相关,比如报错,警告,类编译参数等,这2类状态一般和编辑器插件关系密切,这里不再讨论
在日常开发中RUNTIME用的最多,这是开发人员可以控制的一个状态。
【@Documented】额,不多解释,具体来说是生成说明文档时把类的解释添加进去。
关于注解的方法说明,注解只有方法,没有字段,因为注解也是一个interface,只不过前面加了一个@符号,还有一点是这些方法无法实现,写法和C++的纯虚函数相似
请看id()方法的解释
1
2
3
4
5
6
|
public
int id()
default
0;
/*首先,方法必须是public的,去掉public,默认也是public,接口interface不也是这样么
*
*其次,default默认值不是必须的,方法必须有返回值,返回值可以是java中复杂对象,也可以是基本类型,枚举都行
*如 ElementType[] value();
*/
|
注解定义好了,怎么使用呢,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public
class
TestMain
{
@UserAnnotation(age=20,gender=
"F"
,id=2014,name=
"zhangsan"
)
//注解的使用
private
Object obj;
public
static
void main(String[] args) throws Exception
{
Filed objField = TestMain.
class
.getField(
"obj"
);
UserAnnotation ua = objField.getAnnotation(UserAnnotation.
class
);
//得到注解,起到了标记的作用
System.out.println(ua.age()+
","
+ua.gender()+
","
+ua.id()+
","
+ua.name());
//***进一步操作的话,假设Object要指向一个User类,那么可以讲注解的值给他
TestMain tm =
new
TestMain();
objFiled.set(tm,
new
User(ua.age(),ua.gender(),ua.id(),ua.name()));
//不错吧,将自己的信息送给obj,起到了附加信息的作用
//-----------请自由遐想吧~~,下面来说说注解怎么能获得注解自己的注解-------------
Target t = ua.annotationType().getAnnotation(Target.
class
)
ElementType[] values = t.value();
//~~~~~~~~~~~~~~完了,再一次自由遐想吧~~~~~~~~~~~~~~
Sysout.out.println(
"注意:是遐想,不是瞎想!!"
);
}
}
|
try doing it.