1.什么是注解?
注解是插入代码中的一种注释或者说是一种元数据。
注解相当于一种标记,可加载包、类、属性、方法、方法参数和局部变量上,对程序执行没有影响。
//定义注解
public @interface TestAnnotation{
}
//注解使用
@TestAnnotation
public class Test {
}
2.注解的作用?
最主流应用:替代配置文件
关于配置文件与注解开发的优缺点:
注解优点:提高开发效率高、成本低
注解缺点:耦合性大,并且不利于后期维护
3.元注解
元注解是可以加到注解上的注解,主要包括:@Retention、@Documented、@Target、@Inherited、@Repeatable 5 种。
必写的两个:
- @Retention:当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。
它的取值如下:
RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到JVM中。
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
- @Target:指定了注解运用的地方。@Target 有下面的取值:
ElementType.FIELD 可以给属性进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
4.注解的属性
- 注解只有成员变量没有方法
- 成员变量的定义以“无形参的方法”来声明
- 返回值定义了成员变量的类型
- 在注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组。
- 注解中属性可以有默认值,默认值需要用 default 关键值指定。
@target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation{
int id();default -1;
String message();default "nihao";
}
5.注解的提取
反射:检阅注解,注解通过反射获取。
1.获取类上的注解
-
可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解
-
通过 getAnnotation() 方法来获取 Annotation 对象。
@MyTest(id=1,value="hello")
public class Test {
public static void main(String[] args) {
if(Test.class.isAnnotationPresent(MyTest.class)) {
System.out.println(Test.class.getAnnotation(MyTest.class).value());
}
}
}
2.获取一个成员变量上的注解:
Field user=Test.class.getDeclaredField("username");
MyField anno=user.getAnnotation(MyField.class);
System.out.println(anno.value());
3.获取方法上的注解
Method method=Test.class.getDeclaredMethod("a");
MyMethod anno=method.getAnnotation(MyMethod.class);
System.out.println(anno.value());
6.案例:
- 定义一个注解
- 在一个测试类 上的添加几个方法,并在方法上添加注解
- 添加另一个有main方法的类
运行main方法的时候,需要将带有 注解的方法执行
核心代码:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMethod2 {
}
public class Test3 {
@MyMethod2
public void a() {
System.out.println("aaaa");
}
public void b() {
System.out.println("bbbb");
}
public void c() {
System.out.println("cccc");
}
@MyMethod2
public void d() {
System.out.println("dddd");
}
}
Method[] methods=Test3.class.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyMethod2.class)) {
method.invoke(Test3.class.newInstance());
}
}
最后的输出:
7.Servlet3.0
@WebServlet(urlPatterns="*.do")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("okkkkkkkkkk");
}
}
访问1.do,控制台打印okkkkkkkkkk