很多Java程序员,对Java的注解一知半解,更有甚者,有的人可能连注解是什么都不知道

本文我们用最简单的 demo , 最通俗最短的语言,带你了解注解到底是什么?

先来简单回顾一下基础,我们知道,Java 的源文件编辑后,生成 .class 文件,

  1. .Java源文件,这个是源文件时期
  2. 源文件经过编译生成 .class 字节码文件,这个也是编译时期
  3. .class 加载到内存中,就可以用了,这个是运行期间

如下图

记住以上知识点,下面和注解有关,我们正式来讲注解

本文将从以下 2 个方面来讲解注解

  • 1 注解是什么
  • 2 如何定义一个注解
  • 3 如何使用注解

尤其是第3条,很多人不理解注解,就是因为不知道如何使用注解

3条本文会用最简单的语言来揭示如何使用

一 注解是什么?

一句话,注解就和生活中的标签一样,比如一个人,这个人可能有 学生标签,月光族标签,爱抬杠标签

二 如何定义一个注解

语法: public @interface 注解名 { }

对的, @interface 是个关键字,记住就行了,没有为什么

定义注解就是用@interface ,后面跟上注解名

比如定义一个名字叫 info 的注解,如下

新建一个文件 info.java,代码如下:

package com.demo;

//定义了一个叫做 info 的注解
public @interface info { }

很简单吧,上面就定义了一个叫做 info 的注解,下面有2个问题来了

  • 第一个: info 注解用在什么地方?

    是用到类名上? 还是用在 类的字段上 ? 还是用在类的方法上 ?

  • 第二个:info 注解生命周期(或叫保留策略,我更喜欢叫生命周期)

    注解还有生命周期吗?答案是当然有了

    前面说过,注解类似标签,一个人可能刚毕业,有月光族标签,刚毕业赚的少嘛

    但是有可能过了 3,4 年,技术好了,工资涨上去了,可能就没有月光族标签了

    那么标签有几个生命周期呢?就是本文开头讲的,参考上面的图

    答案是:3 个 ,分别是 源文件期编译期运行期

就是说:有的注解存在于源文件期,有的标签存在于编译期,有的标签存在于运行期

::: tip

运行期的注解用的最多,本文着重讲运行期间,源文件期,编译期比较简单

看懂运行期后,可自行学习另外2个

运行期,也就是注解在运行期还存在

:::

我们接下来给 info 注解定义用在类的字段上,并且是存在于运行期间

先上代码,再解释,代码如下:

@Target(ElementType.FIELD)          //注解作用在类的字段上
@Retention(RetentionPolicy.RUNTIME) //注解存在于运行期
public @interface info { }

由上面代码可以看到,出现了 @Target , @Retention 注解,那么 @Target , @Retention又是什么?

答:@Target, @Retention 是元注解,咋又出来一个元注解,可以望文生义:元就是元始的意思,最开始的意思

举个很简单的例子来帮助了解元注解是什么

比如开发一款 IOS APP 软件,用 xcode 这个软件开发,那么 xcode软件又是用什么开发的?

定义一个注解,用元注解

是不是很类似,如下图

看过上面的图应该能理解了,什么是元注解了吧,就是为了定义注解用的,知道怎么用就行了

就比如我们开发软件,要用到各种各样的开发软件的IDE,我们不用管这些IDE软件是哪个软件开发的

我们只需要知道,元注解就相当于IDE,注解就相当于我们开发的软件,就OK了

回到上面的info的定义,我们来解释一下 Target,Retention 这 2 个注解的用处以及能取哪些值

Target 元注解

用处:用来定义注解的用在的地方,比如是用在类上啊,还是用在字段上啊,还是用在方法上啊等

取值:我们列出几个常用的就行,其它的自行下去查义即可,如下

取值 用在哪
ElementType.TYPE 类或者接口上
ElementType.FIELD 类的字段上
ElementType.METHOD 类的方法上
ElementType.PARAMETER 方法的参数上

Retention 元注解

用处:用来定义注解的生命周期(或叫保留策略,我更喜欢叫生命周期)

取值:就只有3个,如下

取值 存在于哪个时期
RetentionPolicy.SOURCE 源文件期
RetentionPolicy.CLASS 编译期
RetentionPolicy.RUNTIME 源运行时期

::: tip

元注解都是已经定义好的,我们只管用,只管知道怎么用就行

就是我们自定义一个注解时才用到元注解,取几个值,定义一下我们的注解用在哪些地方

存在的时期等,仅此而已

:::


通过上面的叙述,我们小小总结一下

  • 注解就是类似标签一样的东西
  • 注解定义是用 public @interface 注解名 { }
  • 注解是有使用的地方和生命周期的
  • 注解能用在类上,字段上,方法上,参数上等
  • 元注解就是用来定义注解的,就像 xcode 软件是用来开发IOS 软件一样的逻辑

下面我们来讲第三点,也是最重要的一点,我们学会了自定义注解,怎么使用呢?

三 如何使用注解

注解一般是和反射一块用的,不懂反射的,不懂Java的大Class的,一定要看看下面的2篇文章

一篇文章彻底搞懂Java的大Class到底是什么

一篇文章弄懂 Java 反射的使用

我们来扩展一下上面的 info注解,代码如下:

@Target(ElementType.FIELD)          //注解作用在类的字段上
@Retention(RetentionPolicy.RUNTIME) //注解存在于运行期
public @interface info {
String job(); //job属性
String comment(); //comment属性
}

对的,你又看到了注解还能定义属性,记住,就按照上面的定义就行了。

主要看怎么用

我们定义一个工人类Worker,如下:

//工人类
public class Worker {
//工人的名字
public String name; //工人简介方法,打印工作的基本信息
public void show(){ }
}

很简单的一个类,我们在 name 字段上添加我们定义的info注解,如下

public class Worker {

    //注解是能给属性传值的,job和comment和info定义中的相呼应,对,属性就是这样用的
@info(job = "工程师",comment = "工作很努力")
public String name; public void show(){ }
}

上面我们给 name 字段添加了我们自己定义的注解,并且给注解中传了工作的职位是:工程师 ,评价是:工作很努力

我们想在show()方法中,打印出工作的名字,职位,和评价

获取注解中的 job和 comment可以通过反射获取 ,注意看注释,如下

public class Worker {

    //注解是能给属性传的,job和comment和定义中的相呼应
@info(job = "工程师",comment = "工作很努力")
public String name; public void show(){
//1 获取本类的字节码
Class clz = this.getClass(); //2 获取类中定义的字段
Field[] fields = clz.getDeclaredFields(); //3 遍历字段,看看哪个字段有info注解
for (Field field : fields){
//4 判断此字段上是否有 info 注解
info annotation = field.getAnnotation(info.class); //5 如果不为 null ,说明 field上有info注解
if (annotation != null){
//6 通过info注解,获取info注解中的 job和comment
String job = annotation.job();
String comment = annotation.comment(); //7 打印出来
System.out.println("我是:" + this.name + " 我的职位是:" + job + " 我的评价是:" + comment);
}
}
}
}

通过上面可以看出,使用注解步骤如下:

  1. 获取类的 Class ,也就是类的字节码
  2. 获取类的所有字段的字码码数组
  3. 遍历字段
  4. 通过 info annotation = field.getAnnotation(info.class) 获取字段上对应的注解
  5. 通过注解,获取注解中传的值

我们再来写一个 main 函数,调用上面那段代码:如下

public class Demo1 {
public static void main(String[] args){
Worker worker = new Worker();
worker.name = "待兔,www.helloworld.net 站长";
worker.show();
}
}

打印如下:

我是:待兔,www.helloworld.net 站长 我的职位是:工程师 我的评价是:工作很努力

本文到此,几乎讲完了,注解的很多其它的东西还没有讲,不过不重要,本文最重要的让你明白什么是注解,怎么定义注解,怎么使用注解

至于注解其它的知识,比如注解怎么用在方法上,用上类上,等等,都是类似,只需要查一下就行了。

网上很多文章 ,只要能通过本文把注解弄明白了,了解注解其它的就简单了。

一篇文章通俗易懂的让你彻底理解 Java 注解的更多相关文章

  1. (转)深入理解Java注解类型(@Annotation)

    背景:在面试时候问过关于注解的问题,工作中也用到过该java的特性,但是也没有深入的了解. 秒懂,Java 注解 (Annotation)你可以这样学 ps:注解最通俗易懂的解释 注解是一系列元数据, ...

  2. 理解Java注解类型

    一. 理解Java注解 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类.而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy ...

  3. 你真的理解Java 注解吗?

    你真的理解Java 注解吗? 1.什么是注解? 官方解释: Java 注解用于为 Java 代码提供元数据.作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的.Java ...

  4. 深入理解 Java 注解

    深入理解 Java 注解 本文内容基于 JDK8.注解是 JDK5 引入的,后续 JDK 版本扩展了一些内容,本文中没有明确指明版本的注解都是 JDK5 就已经支持的注解.

  5. 深入理解Java注解类型(@Annotation)

    http://blog.csdn.net/javazejian/article/details/71860633  出自[zejian的博客] java注解是在JDK5时引入的新特性,鉴于目前大部分框 ...

  6. 理解java注解

    @是java注解,即annotation. 注解功能可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件. Java注解是附加在代码中的一些元信息,用于一些工具在编译 ...

  7. 【算法】计算一篇文章的单词数(C、Java语言实现)

    1. C语言:一个字符一个字符的读取 (有空再贴出来) 2.Java语言:按行读取,并用正则分割成多个单词,再用MapReduce并行计算单词数 (我使用的是ieda,有些地方跟eclipse有点区别 ...

  8. java基础强化——深入理解java注解(附简单ORM功能实现)

    目录 1.什么是注解 2. 注解的结构以及如何在运行时读取注解 2.1 注解的组成 2.2 注解的类层级结构 2.3 如何在运行时获得注解信息 3.几种元注解介绍 3.1 @Retention 3.2 ...

  9. 深入理解Java 注解原理

    *注解的用途 注解(Annotation)是JDK1.5引入的新特性,包含在java.lang.annotation包中,它是附加在代码中的一些元信息,将一个类的外部信息与内部成员联系起来,在编 译. ...

随机推荐

  1. Win64 驱动内核编程-31.枚举与删除映像回调

    枚举与删除映像回调 映像回调可以拦截 RING3 和 RING0 的映像加载.某些游戏保护会用此来拦截黑名单中的驱动加载,比如 XUETR.WIN64AST 的驱动.同理,在反游戏保护的过程中,也可以 ...

  2. 三、jmeter常用的元件及组件

    一.HTTP cookie Manager 用来储浏览器产生的用户信息,Stepping Thread Group 可用于模拟阶梯加压! 二.HTTP Cache Manager 缓存管理器(模拟浏览 ...

  3. 在服务器上使用 smart http 搭建 Git 服务器

    前言 最近一直在写 django 网页的代码,随着代码的量越来越大,管理起来也有点复杂(当然,有在使用 git 进行代码管理).同时由于有不同的工作环境,有些工作环境对 ssh 的访问有限制,所以想到 ...

  4. 二、多线程之Thread中run 和start 区别

    Thread使用run 和start 区别 结论:run()方法将作为当前调用线程本身的常规方法调用执行,并且不会发生多线程. System.out.println("开始测试多线程&quo ...

  5. 算法学习笔记1语法 (C++组)持续更新

    关于 #include <cstdio> 包含printf();和scanf(); c++中printf.scanf比cout.cin效率高很多 算法题里cin.cout可能超时,虽然可以 ...

  6. valgrind 内存泄漏分析

    概述 valgrind 官网 https://www.valgrind.org/ valgrind 是 Linux 业界主流且非常强大的内存泄漏检查工具.在其官网介绍中,内存检查(memcheck)只 ...

  7. python爬虫——抖音数据

    最近挺火的抖音短视频,不仅带火了一众主播,连不少做电商的也进驻其中,于是今天我来扒一扒这火的不要不要的抖音数据: 一.抓包工具获取用户ID 对于手机app数据,抓包是最直接也是最常见的手段,常用的抓包 ...

  8. FreeSWITCH的安装与使用

    FreeSWITCH

  9. KMP板子(其实还没完全懂...)

    KMP模板 1.next数组的实际含义 next数组从-1开始,主串a,子串b,next[j]=k,满足b[0,k-1]==b[j-k,j-1],k同时也为b子串前缀的下标,j为b子串后缀的下标 ge ...

  10. [c++] 开发问题

    语言中的很多细节都是为了应对实际开发中会遇到的问题 当编写程序时,我们使用的定义多数不是自己写的,如sqrt(),是很多年前别人写的,我们只是使用它们 在C++中,对于"别处"定义 ...