注解

一、认识注解

先看百度百科对java注解的解释:

定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

作用分类:

①编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】

② 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】

③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】

提到的元数据,可以理解为描述数据的数据,看起来很绕,元注解也是描述注解的注解,后面说。

Annotation都是java.lang.annotation.Annotation接口的子接口,注解是一种特殊的接口,从代码格式上来看确实是,是在interface前加了一个@符号,格式为@interface xxx{}

二、JDK内置注解

jdk就存在注解,比如我们用eclipse子类覆盖父类方法时候用快捷间alt+/会自带在方法名称上面贴上一个@Override的标签。

  • @Override

    这个就是在子类覆盖父类的方法时候,经常遇到

  • @Deprecated

    这个元素是用来标记过时的元素,想必大家在日常开发中经常碰到。编译器在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量。 如java.util.Data类中有很多过时的方法

  • @SupressWarings

    抑制警告,有很多人有代码洁癖,看到黄色的警告不爽,用它就可以抑制住。

  • @SafeVarargs

    java7出现的,抑制堆污染警告,有点自欺欺人的感觉。

三、元注解

元注解就是注解的注解,来看一下有哪些元注解

  • @Retention

    Retention英文是保留的意思,在这里可以约束注解的存活周期,代码运行有三个周期,分别为Source(源代码)、Class(字节码)、Runtime(运行时期) 三个时期的值保留在RetentionPolicy这个枚举类中。所以我们可以这样来玩,

    @Retention(RetetionPolicy.常量值)//RESOURCE,CLASS,RUNTIME

  • @Target

    Target是目标的意思,这里约束这个注解在那可以贴(类,方法,构造器,参数等),位置的常量在ElementType这个枚举类中

    @Target({ElementsType.常亮值})//TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE表示类,接口,枚举

  • @Documented

    Document文档的意思,也就是使用这个标签到时候会带到API文档中去

  • @Inherited

    Inherited是遗传的意思,顾名思义,这个注解会遗传到子类去

  • @Repeatable 可重复的,Java8的一个新特性

四、自定义注解

1.注解的属性

在注解中定义属性,必须是8 种基本数据类型外加 类、接口、注解及它们的数组。不能是Integer..注解中属性可以有默认值,默认值需要用 default 关键值指定。

如:

@interface TestAnnotation{
int id() default 0;
String msg() default "hello";
}
@TestAnnotation(id = 3,msg = "aa")
class Test1{ } //当注解中只有一个value属性时候,贴标签的时候可以省略value。
//当注解中没有属性时,括号都可以省略(override注解)
@interface Test1Annotation{
int[] value();
}
@Test1Annotation({1,2})
class Test2{ }

2.用反射操作注解

注解可以在类Class,方法Method,字段Field,构造器Constructor上等,所以在各自的类中都存在获取注解的API

 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
Annotation[] getAnnotations() 返回此元素上存在的所有注释。
<Annotation> getAnnotation(Class annotationClass)如果存在该元素的指定类型的注释,则返回这些注释对象,否则返回 null。 获取注解对象

自定义一个注解:

@Target({TYPE, FIELD, METHOD})//注解可以放的目标
@Retention(RetentionPolicy.RUNTIME)//注解保留周期
public @interface AnnotationTest {
int id();
String name();
}

测试一下这个自定义的注解:

@AnnotationTest(id = 1,name = "na")
class Test{
public static void main(String[] args) throws Exception {
//判断Test(类元素)是否应用了这个注解
boolean hasAnnotation = Test.class.isAnnotationPresent(AnnotationTest.class);
if(hasAnnotation){
//获取注解对象
AnnotationTest t = Test.class.getAnnotation(AnnotationTest.class);
System.out.println(t.name());
System.out.println(t.id());
//获取所有的注解s
Annotation[] ans = Test.class.getAnnotations();
for (Annotation an : ans) {
System.out.println(an);
}
}
System.out.println("============");
//获取方法中上的注解
boolean has = Test.class.getMethod("work").isAnnotationPresent(AnnotationTest.class);
if(has){
AnnotationTest an = Test.class.getMethod("work").getAnnotation(AnnotationTest.class);
System.out.println(an.name());
}
}
@AnnotationTest(id = 0,name="hello")
public void work(){
}
}

结果为:

na
1
@annotation.AnnotationTest(id=1, name=na)
============
hello

五、注解的用途

实践:模拟Junit4.x

Junit是做单元测试的,junit4用了注解,用法是在一个公共无参的方法贴上一个@Test标签表示要测试这个方法,但是在测试之前有可能会出现一些初始化操作,在结束后可能需要释放一些资源,需要初始化的方法上面贴上一个@Before,Test之后需要执行的需要贴上@After。

现在我们来自定义注解来模拟一下这些操作,需要在这里提的是,其实注解本身没什么意义,需要人为的设置它完成一些功能。

我们先定义三个注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAfter { }
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyBefore { }
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest { }

来一个测试这些注解功能的类

public class Employee {
@MyBefore
public void init(){
System.out.println("-------初始化-------");
}
@MyAfter
public void end(){
System.out.println("-------销毁---------");
}
@MyTest
public void save() {
System.out.println("保存操作");
}
@MyTest
public void delete() {
System.out.println("删除操作");
}
@MyBefore
public void ddd(){
System.out.println("怎么说呢?");
}
}

好了,接下来我们就得具体去设置这个注解的意义

思路和步骤:

  • 获取Employee类的字节码对象,得到所有的方法

    • 对所有方法进行迭代,将三类注解分别存储,把有@MyBefore注解的存在beforeList,带有@MyAfter存在afterList,带有@MyTest存在testList

      对testList集合迭代,在迭代 过程中先执行beforeList中的方法,在执行afterList中的方法
public class JunitTest {
public static void main(String[] args) throws Exception {
//得到Employee中所有的方法
Method[] mds = Employee.class.getDeclaredMethods();
//创建Employee的对象,用来执行方法
Employee e = Employee.class.newInstance();
//用集合存储三类注解标注的方法
List<Method> beforeList = new ArrayList<>();
List<Method> afterList = new ArrayList<>();
List<Method> testList = new ArrayList<>();
//对所有的方法进行迭代,分类
for (Method md : mds) {
if(md.isAnnotationPresent(MyBefore.class)){
beforeList.add(md);
}else if(md.isAnnotationPresent(MyAfter.class)){
afterList.add(md);
}else if(md.isAnnotationPresent(MyTest.class)){
testList.add(md);
}
}
//在对test迭代的过程中,先执行所有被before注解了的方法,然后执行test注解的方法,最后再执行after注解了的方法
for (Method method : testList) {
for (Method before : beforeList) {
before.invoke(e); //方法都没有参数
}
method.invoke(e); for (Method after : afterList) {
after.invoke(e);
}
}
}
}

结果:

-------初始化-------
怎么说呢?
删除操作
-------销毁---------
-------初始化-------
怎么说呢?
保存操作
-------销毁---------

java之美妙的注解的更多相关文章

  1. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  2. Java学习记录-注解

    注解 一.org.springframework.web.bind.annotation ControllerAdviceCookieValue : 可以把Request header中关于cooki ...

  3. JUnit 4 使用 Java 5 中的注解(annotation)

    JUnit 4 使用 Java 5 中的注解(annotation),以下是JUnit 4 常用的几个 annotation 介绍@Before:初始化方法@After:释放资源@Test:测试方法, ...

  4. Java中万恶的注解

    本文由码农网 – 孙腾浩原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 当Java 1.5引入注解,企业开发者对简化EJB和其他企业产品开发抱有很大期望.可以看一看同一时期的一篇文章 ...

  5. Java 8 可重复注解与类型注解

    Java 8 可重复注解与类型注解 Java 8 对注解处理提供了两点改进:可重复的注解及可用于类型的注解. // 首先要提供一个容器,MyAnnotation 才能用于可重复注解 @Target({ ...

  6. 转: JaxbContext生成xml文件或java类对象转化注解

    JAXB(Java API for XML Binding),提供了一个快速便捷的方式将Java对象与XML进行转换.在JAX-WS(Java的WebService规范之一)中,JDK1.6 自带的版 ...

  7. Java基础教程(16)--注解

    一.注解基础知识 1.注解的格式   最简单的注解就像下面这样: @Entity   @符号指示编译器其后面的内容是注解.在下面的例子中,注解的名称为Override: @Override void ...

  8. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  9. Java复习——枚举与注解

    枚举 枚举就是让某些变量的取值只能是若干固定值中的一个,否则编译器就会报错,枚举可以让编译器在编译阶段就控制程序的值,这一点是普通变量无法实现的.枚举是作为一种特殊的类存在的,使用的是enum关键字修 ...

随机推荐

  1. VS2010/MFC编程入门之二十七(常用控件:图片控件Picture Control)

    上一节中鸡啄米讲的是滚动条控件,本节主要讲一种简单实用的控件,图片控件Picture Control.我们可以在界面某个位置放入图片控件,显示图片以美化界面. 图片控件简介 图片控件和前面讲到的静态文 ...

  2. Python ConfigParser的使用

    1.基本的读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该sect ...

  3. bzoj1605 / P2905 [USACO08OPEN]农场危机Crisis on the Farm

    P2905 [USACO08OPEN]农场危机Crisis on the Farm 发现总步数$k<=30$,考虑用$k$瞎搞 设$f[u][i][j]$表示已经吹$u$次哨,全体奶牛向右走$i ...

  4. jQuery获取不到隐藏DIV的高度和宽度

    今天做公司订单系统的修改,有同事将订单维护的四个部分拆成了四个小的tab页,由于数据表格时动态加载,所以表格的高度是动态变化的,可不知怎么,先点哪个哪个的高度就正常,其他的都是最小值,这下蒙了,这个找 ...

  5. tcpdump 的正确食用方法

    目录 tcpdump 使用笔记 重要报文头 字段表 ip header tcp header 基础使用 高级版本 指定ttl(通过ttl能够确定系统的类型) tcpdump 使用笔记 重要报文头 字段 ...

  6. Java网络编程学习A轮_03_抓包分析TCP四次挥手

    参考资料: http://www.jellythink.com/archives/705 示例代码: https://github.com/gordonklg/study,socket module ...

  7. Tensorflow一些常用基本概念与函数(四)

    摘要:本系列主要对tf的一些常用概念与方法进行描述.本文主要针对tensorflow的模型训练Training与测试Testing等相关函数进行讲解.为‘Tensorflow一些常用基本概念与函数’系 ...

  8. HDU 5586 简单最大子段和变形

    Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  9. UVA-1660 Cable TV Network (最小割)

    题目大意:给一张n个点.m条边的无向图,求最小点割集的基数. 题目分析:求无向图最小点割集的基数可以变成求最小割.考虑单源s单汇t的无向图,如果要求一个最小点集,使得去掉这个点集后图不再连通(连通分量 ...

  10. Leetcode 62

    //从理解二维dp到简化成一维dp我用了一年的时间class Solution { public: int uniquePaths(int m, int n) { vector<); ;i &l ...