概念
说明程序用的,给计算机看的
作用分类
- 编写文档:通过代码标识里的注解生成文档(doc文档)
- 代码分析:通过代码里标识的注解对代码进行分析(使用反射)
- 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查(override)
JDK中预定义好的一些注解
- @Override:检测被该注解标注的方法是否是继承自分类(接口)的,是否是重写的方法。
- @Deperecated:该注解标注的内容表示已过时。
- @suppressWarnings:压制警告。一般传入参数all表示压制所有警告
eg:@SuppressWarnings("all")
自定义注解
-
格式:
元注解
public @interface 注解名称{} -
本质:注解的本质就是一个接口,该接口默认继承Annotation接口
eg:public interface extends java.lang.annotation.Annotation{}
-
属性:接口中的抽象方法
要求:
1,属性的返回值类型的取值范围
基本数据类型
String
枚举
以上类型的数组
eg:
public @interface Myanno1 {
int age();
String name();
String[] address();
}
2,定义了属性在使用时需要给属性赋值
如果定义属性时,使用default关键字给属性默认值,则使用注解时,可以不进行属性赋值
eg:注解定义
public @interface Myanno2 {
String name() default "小白";
}
使用注解时:
@Myanno2
public class Anno2 {
}
如果只有一个属性需要赋值且属性名称是value时,可以省略value,直接定义值即可
eg:注解定义
public @interface Myanno {
String value();
}
使用注解时:
@Myanno("小白")
public class Anno3 {
}
数组赋值时使用{}包裹。如果数组中只有一个值则{}可以省略
eg:注解定义
public @interface Myanno1 {
int age();
String name();
String[] address();
}
注解使用
//@Myanno1(age=1,name="小白",address={"云南","北京"})
@Myanno1(age=1,name="小白",address="云南")
public class Anno1 {
}
- 元注解:用于描述注解的注解。java定义好的注解。
@Target:描述注解能够作用的位置。属性:ElementType(取值:
Type:作用于类上
METHOD:作用于方法上
FIELD:作用于成员变量上)
@Retention:描述注解被保留的阶段。属性(枚举类型):RetentionPolicy(取值:CLASS :在类加载阶段
SOURCE:源代码阶段
RUNTIME:运行时阶段 )
@Documented:描述注解是否抽取到api文档中。
@Inherited:描述注解是否被子类继承。
eg:
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
//@Retention(RetentionPolicy.CLASS)
//@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface YAnno {
}
在程序中使用(解析)注解
1,获取注解定义的位置的对象(class,method,field)
2,获取指定的注解(getAnnotation(class)//其实就是生成了一个该注解接口的子类实现对象)
3,调用注解中的抽象方法获取配置属性的值。
eg:
@TAnno(className ="com.example.javaoop2.annotation.Demo2",methodName = "show")
public class Test1 {
public static void main(String[] args)throws Exception{
//1获取该类的Class对象
Class<Test1> test1Class=Test1.class;
//2获取该类上的TAnno注解对象
TAnno tAnno=test1Class.getAnnotation(TAnno.class);
//调用注解的抽象方法
String className=tAnno.className();
String methodName=tAnno.methodName();
System.out.println(className);
System.out.println(methodName);
}
}
小案列
通过注解实现传入不同参数调用不同类的不同方法
分别写两个类Demo1和Demo2里面都有show方法。
eg:
public class Demo1 {
public void show(){
System.out.println("我是Demo1,我show");
}
}
public class Demo2 {
public void show(){
System.out.println("我是demo2...我show");
}
}
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TAnno {
String className();
String methodName();
}
测试类
/**
* 通过注解实现传入不同参数调用不同类的不同方法
*/
@TAnno(className ="com.example.javaoop2.annotation.Demo2",methodName = "show")
public class Test1 {
public static void main(String[] args)throws Exception{
//1获取该类的Class对象
Class<Test1> test1Class=Test1.class;
//2获取该类上的TAnno注解对象
TAnno tAnno=test1Class.getAnnotation(TAnno.class);
//调用注解的抽象方法
String className=tAnno.className();
String methodName=tAnno.methodName();
System.out.println(className);
System.out.println(methodName);
//通过反射机制获取传入类的Class对象
Class myclass=Class.forName(className);
Object obj=myclass.newInstance();
//通过反射机制获取注解传入的方法
Method myMethod=myclass.getMethod(methodName);
//执行该方法.
myMethod.invoke(obj);
}
}
结果