一、Java注解概述
1. 什么是注解?
注解,或者叫做注释类型,英文单词是:Annotation
注解Annotation是一种引用数据类型,编译之后也是生成xxx.class文件。
2. 注解怎么使用,用在什么地方?
第一:注解使用时的语法格式是:@注解类型名
第二:注解可以出现在类上、接口上、属性上、方法上、变量上、枚举上等,注解还可以出现在注解类型上。
3. 什么是元注解?
用来标注“注解类型”的“注解”,称为元注解。
常见的元注解:Target,Retention …
4. JDK内置了哪些注解呢?
java.lang包下的注释类型:Deprecated、Override、SuppressWarnings…
二、注解基本语法
1. 自定义注解
语法格式:
[修饰符列表] @interface 注解类型名{
}
例子:
public @interface MyAnnotation {
}
2. 注释中定义属性
注解中属性的类型可以是:
byte、short、int、long、float、double、boolean、char、String、Class、枚举类型,以及以上每一种的数组形式。
public @interface MyAnnotation {
//我们通常在注解当中可以定义属性,属性看着像方法,但实际上我们称之为属性。
String name();
String color();
//属性指定默认值
int age() default 25;
}
注意:如果一个注解当中有属性,那么必须给属性赋值,除非该属性使用default指定了默认值。否则会报错。
3. 给属性赋值
//格式:@MyAnnotation(属性名=属性值,属性名=属性值,属性名=属性值)
//例子:
@MyAnnotation(name = "zhangsan", color = "红色")
4. value属性
如果一个注解的属性的名字是value,并且只有一个属性的话,在使用的时候,该属性名可以省略。
例如:
public @interface MyAnnotation {
String value();
}
public class MyAnnotationTest {
@MyAnnotation(value = "hehe")
public void doSome(){
}
//可以省略属性名value
@MyAnnotation("haha")
public void doOther(){
}
}
三、Override注解和Deprecated注解
Override
这个注解只能标注方法,当编译器看到方法上有这个注解时,就会自动检查该方法是否重写了父类的方法,如果这个方法不是重写父类的方法,编译器报错。
注意:这个注解是给编译器做参考的,只是在编译阶段起作用,和运行阶段没有关系。
JDK lang包下的Override注解源代码:
@Target(ElementType.METHOD) //表示Override只能标注方法
@Retention(RetentionPolicy.SOURCE) //表示Override只被保留在java源文件中。
public @interface Override {
}
Deprecated
这个注解主要是向其它程序员传达一个信息:告知已过时,有更好的解决方案存在。所以不鼓励程序员使用被 @Deprecated 注释的元素。
JDK lang包下的Deprecated注解源代码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
String since() default "";
boolean forRemoval() default false;
}
四、Target注解
Target
这是一个元注解,是一个用来标注 注解类型 的注解。这个Target注解用来标注“被标注的注解”可以出现在哪些位置上。
Target源码:
@Documented
@Retention(RetentionPolicy.RUNTIME) //表示Target注解被保存在class文件中,可以被反射
@Target(ElementType.ANNOTATION_TYPE) //表示Target注解只能标注注解类型,即Target是一个元注解
public @interface Target {
ElementType[] value();
}
Target的用法:
@Target(ElementType.METHOD) //表示“被标注的注解”只能标注方法。
@Target({ElementType.TYPE, ElementType.METHOD}) //表示“被标注的注解”只能标注类、方法
五、Retention注解
Retention
这是一个元注解,是一个用来标注 注解类型 的注解。这个Retention注解用来标注“被标注的注解”最终保存在哪里。
Retention源码:
@Documented
@Retention(RetentionPolicy.RUNTIME) //表示Retention注解被保存在class文件中,可以被反射
@Target(ElementType.ANNOTATION_TYPE) //表示Retention注解只能标注注解类型,即Retention是一个元注解
public @interface Retention {
RetentionPolicy value();
}
//RetentionPolicy源码
public enum RetentionPolicy {
SOURCE,CLASS,RUNTIME
}
Retention的用法:
@Retention(RetentionPolicy.SOURCE) //表示该注解只被保留在java源文件中。
@Retention(RetentionPolicy.CLASS) //表示该注解被保存在class文件中。
@Retention(RetentionPolicy.RUNTIME) //表示该注解被保存在class文件中,并且可以被反射机制所读取。
六、反射注解
//自定义注解
@Retention(RetentionPolicy.RUNTIME) //希望这个注解可以被反射
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String username();
String password();
}
//测试反射注解
public class MyAnnotationTest {
@MyAnnotation(username = "admin", password = "456456")
public void doSome(){
}
public static void main(String[] args) throws Exception{
// 获取MyAnnotationTest的doSome()方法上面的注解信息。
Class class = Class.forName("com.bjpowernode.java.annotation6.MyAnnotationTest");
// 获取doSome()方法
Method doSomeMethod = c.getDeclaredMethod("doSome");
// 判断该方法上是否存在这个注解
if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.username());
System.out.println(myAnnotation.password());
}
}
}
七、注解在开发中的作用
可完成一些特殊的需求,例如:
假设有这样一个注解,叫做:@Id,这个注解只能出现在类上面,当一个类上有这个注解的时候,要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常,如果有这个属性则正常执行!