先引用一下百度百科的名词解析:

定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用分类:
①编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
② 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】

下面开始正文:

概述:

就如上面所说,注解有几种用途,第一种是编写文档,这种注解会在javadoc中存在;

第二种是代码分析,这需要使用 反射 的api去解析注解;

第三种类是提供编译时的检查,如 deprecated 这些,编译的时候会产生警告信息。

举几个例子:

1、下面的例子,注解使用了@Documented注解,这意味着,我们的注解会在 javadoc 生成的文档中出现,另外一个@Retention的用途下面会说到

  1. package com.ruby;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6.  
  7. @Documented
  8. @Retention(RetentionPolicy.SOURCE)
  9. public @interface ClassPreamble {
  10. String author();
  11. }

  使用:

  1. @ClassPreamble(
  2. author = "ruby"
  3. )
  4. public class Main ...

  

2、代码分析(我们拙劣地模拟一下Spring Boot的路由注解)

代码目录结构:

RequestMapping注解定义:

  1. package com.ruby.annotation;
  2.  
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7.  
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Target(ElementType.METHOD)
  10. public @interface RequestMapping {
  11. String value() default "/";
  12. }

  

Home控制器定义:

  1. package com.ruby.controller;
  2.  
  3. import com.ruby.annotation.RequestMapping;
  4.  
  5. public class Home {
  6. @RequestMapping("test")
  7. public void HelloWorld() {
  8. System.out.println("HelloWorld !");
  9. }
  10. }

使用方法(命名不是太规范,test一般用于测试文件命名):关键是main方法里面通过反射去解析注解的代码,其他两个方法只是工具方法(用以获取包下面所有类)

  1. package com.ruby.test;
  2.  
  3. import com.ruby.annotation.RequestMapping;
  4.  
  5. import java.io.File;
  6. import java.io.IOException;
  7. import java.lang.reflect.InvocationTargetException;
  8. import java.lang.reflect.Method;
  9. import java.net.URL;
  10. import java.util.ArrayList;
  11. import java.util.Enumeration;
  12. import java.util.List;
  13.  
  14. public class TestHome {
  15. public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException{
  16. String route = "test";
  17.  
  18. Class[] classes = getClasses("com.ruby.controller");
  19. for (Class cls : classes) {
  20. Method[] methods = cls.getMethods();
  21. for (Method method : methods) {
  22. RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
  23. if (requestMapping != null) {
  24. String mapping = requestMapping.value();
  25. if (mapping.equals(route)) {
  26. method.invoke(cls.newInstance());
  27. }
  28. }
  29. }
  30. }
  31. }
  32.  
  33. /**
  34. * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
  35. *
  36. * @param packageName The base package
  37. * @return The classes
  38. * @throws ClassNotFoundException
  39. * @throws IOException
  40. */
  41. private static Class[] getClasses(String packageName)
  42. throws ClassNotFoundException, IOException {
  43. ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  44. assert classLoader != null;
  45. String path = packageName.replace('.', '/');
  46. Enumeration<URL> resources = classLoader.getResources(path);
  47. List<File> dirs = new ArrayList<File>();
  48. while (resources.hasMoreElements()) {
  49. URL resource = resources.nextElement();
  50. dirs.add(new File(resource.getFile()));
  51. }
  52. ArrayList<Class> classes = new ArrayList<Class>();
  53. for (File directory : dirs) {
  54. classes.addAll(findClasses(directory, packageName));
  55. }
  56. return classes.toArray(new Class[classes.size()]);
  57. }
  58.  
  59. /**
  60. * Recursive method used to find all classes in a given directory and subdirs.
  61. *
  62. * @param directory The base directory
  63. * @param packageName The package name for classes found inside the base directory
  64. * @return The classes
  65. * @throws ClassNotFoundException
  66. */
  67. private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
  68. List<Class> classes = new ArrayList<Class>();
  69. if (!directory.exists()) {
  70. return classes;
  71. }
  72. File[] files = directory.listFiles();
  73. for (File file : files) {
  74. if (file.isDirectory()) {
  75. assert !file.getName().contains(".");
  76. classes.addAll(findClasses(file, packageName + "." + file.getName()));
  77. } else if (file.getName().endsWith(".class")) {
  78. classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
  79. }
  80. }
  81. return classes;
  82. }
  83. }

  

3、编译时检查:如@SuppressWarnings,如有些废弃的方法调用之后会有警告信息,你可以使用@SuppressWarnings注解:@SuppressWarnings("deprecation"),这样编译的时候就不会产生警告信息了。

注解定义

注解定义的方法类似接口定义(上面有例子了),只是在interface关键字前面多了个@符号,注解定义上面也还可以有其他注解(下面详说),注解体里面的元素基本格式都一致,类型名称 + 变量名 + 括号 + default xxx; 默认值的提供是可选的。类型可以是普通类型,也可以是类啊、异常啊这些。

接下来要说的发图吧,比较清晰:

注解分类:

1、普通注解,如:@Deprecated、@Override、@SuppressWarnings、@SafeVarargs等

2、注解其他注解的注解(比较拗口):记重点了,比较关键的是@Retention、@Target

别的不说,先发图,看图比较清晰:

先说@Retention,这个很重要,如果我们要在运行时使用定义的注解,一定不要写错了,默认是不会到运行时还存在的

使用方法:在注解定义处使用:

  1. @Retention(RetentionPolicy.SOURCE)
  2. public @interface ClassPreamble {
  3. String author();
  4. }

有三个可选的选项:(默认是RetentionPolicy.CLASS)

1、RetentionPolicy.SOURCE,如果使用该选项,我们的注解只会在源代码存在,编译之后就没有了,我们去看编译之后的 class 文件,会发现注解已经不存在了。但是如果我们不写@Retention 的话,编译后的 class 文件还会有该注解,因为默认是RetentionPolicy.CLASS。

2、RetentionPolicy.CLASS(默认),使用该选项,我们的注解会在源代码和class文件中存在

3、RetentionPolicy.RUNTIME,使用该选项,我们的注解会一直存在,我们可以在运行的时候去获取注解信息,然后做相应处理。

@Document 这个注解会在 javadoc 生成的文档中出现

@Target,这也算是一个比较重要的注解,指明了该注解可以用在什么地方,好比如,你指定了一个注解的Target为ElementType.METHOD,那么这个注解只能用在方法上,而不能用在field或者type上,当然你也可以同时指定多个,如:

  1. @Target({ElementType.FIELD, ElementType.METHOD})

 可用类型如上图。

@Repeatable 指明该注解是否可以多次使用

好了,就这么多了,其他还不是太了解,上面只是看文档总结的东西,

其实最重要的还是@Retention,如果要在运行时也用到注解信息,那么必须指定  Retention.RUNTIME 参数,否则通过反射去获取注解是获取不到的。

与此相关的另外的知识就是反射了,有空再补充。

java 注解详解的更多相关文章

  1. 《Java基础知识》Java注解"@"详解

    Java注解含义: Java注解,顾名思义,注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的.Java注解又叫java标注,java提供了一套机制,使得 ...

  2. 【Java基础】Java 注解详解

    对于Java注解,我之前的印象是很模糊的,总觉得这个东西经常听说,也经常用,但是具体是怎么回事,好像没有仔细学习过,说到注解,立马想到@Controller,仅此而已. 对于Java注解,我咨询过一些 ...

  3. Java注解详解

    Java1.5引入了注解,注解作为程序的元数据嵌入到程序中.注解可以被一些解析工具或者编译工具进行解析.我们也可以声明注解在编译过程或者执行时产生作用. 创建Java自定义注解: package co ...

  4. Java基础13:反射与注解详解

    Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...

  5. java中的注解详解和自定义注解

    一.java中的注解详解 1.什么是注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: @Override public Str ...

  6. Java Servlet详解(体系结构+注解配置+生命周期)

    Java Servlet详解(注解配置+生命周期) 什么是Servlet : (Server applet)? 顾名思义:服务端的小程序 Servlet只是一个接口,定义了Java被浏览器访问到(To ...

  7. Java Annotation详解 理解和使用Annotation

    系统中用到了java注解: 查了一下如何使用注解,到底注解是什么: (1)创建方法:MsgTrace Java Class==> 在Create New Class中: name:输入MsgTr ...

  8. @RequestBody, @ResponseBody 注解详解(转)

    原文地址: https://www.cnblogs.com/qq78292959/p/3760651.html @RequestBody, @ResponseBody 注解详解(转) 引言: 接上一篇 ...

  9. SpringMVC 常用注解 详解

    SpringMVC 常用注解 详解 SpringMVC 常用注解 1.@RequestMapping                                      路径映射 2.@Requ ...

随机推荐

  1. 技本功丨用短平快的方式告诉你:Flink-SQL的扩展实现

    2019年1月28日,阿里云宣布开源“计算王牌”实时计算平台Blink回馈给ApacheFlink社区.官方称,计算延迟已经降到毫秒级,也就是你在浏览网页的时候,眨了一下眼睛,淘宝.天猫处理的信息已经 ...

  2. 常用JDBC数据库驱动包和类名

    MySQL数据库: 1)驱动包:https://mvnrepository.com/artifact/mysql/mysql-connector-java(下载路径) 2)驱动类名:com.mysql ...

  3. Python基础灬补充(循环、格式化输出)

    for循环&格式化输出 chinese_zodiac = '鼠牛虎兔龙蛇马羊猴鸡狗猪' for year in range(2000, 2013): print("%s年的生肖是:% ...

  4. 性能度量RMSE

    回归问题的典型性能度量是均方根误差(RMSE:Root Mean Square Error).如下公式. m为是你计算RMSE的数据集中instance的数量. x(i)是第i个实例的特征值向量 ,y ...

  5. leetcode个人题解——#36 valid Sudoku

    思路题目里已经给出来了,判断是否是一个有效数独,只需满足以下三个条件: 1.同行元素不重复且1-9都有: 2.同列元素不重复且1-9都有: 3.每个粗线分隔的3*3的小九宫格元素不重复且1-9都有. ...

  6. MySQL 中的数据类型介绍

    1.MySQL 数据类型 MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 2.数值类型(12) 2.1. ...

  7. HTML&CSS实体

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  8. 读着读着《构建之法》(Build To Win) 越精神的白雪儿的思考

    哲学家的宗旨是:我思,故我在 科学家的宗旨是:我发现,故我在 工程师的宗旨是:我构建,故我在 ——<工程学--无尽的前沿> 序言:珍惜角色“人”,注重实践“物” <构建之法>, ...

  9. 测试——约跑APP

    项目名:约跑APP 用户需求规格说明书URL:http://www.cnblogs.com/liquan/p/6071804.html 组长博客URL:http://www.cnblogs.com/l ...

  10. 常用的一些sql

    --根据某一列中包括的逗号将一行数据变多行 select a,c from (with test as (select 'abc' a,'1,2,3' c from dual e) select a, ...