Thinking in Java这本书很久前就购买了,打算有时间看一下,因为自己的时间被自己安排的紧张,也没时间看书。黄师傅上次课程讲到了注解的使用和反射的使用,今天打算学习一下注解。该文章参考Thinking in Java的第20章Annotation。

简单介绍

注解为我们代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。

内置注解:

JavaSE5内置了3个注解

  • @Override 覆盖超类中的方法,如果不小心拼写错误,或者方法签名对不上覆盖的方法,编译器会发出错误提示
  • @Deprecated 如果程序员使用了注解为它的元素,编译器会发出警告信息
  • @Suppress Warnings 关闭不当的警告信息,在JavaSE5之前版本,也可以使用该注解

除了这三个注解,Java还提供了四种胡姐,负责新注解的创建,我们将稍后学习。

当我们创建描述符合性质的类和接口时,一旦其中包含了重复性的工作,那就可以考虑使用注解来简化与自动化该过程,例如

在EJB中存在很多的额外工作,EJB3.0就是使用注解消除了它们。

基本语法

编译器要确保其构造路径上必须有@Test注解的定义,我们可以创建一个通过反射机制来运行testExecute()方法的工具。

package littlepage.annotation.test1;

public class Testable {
public void execute(){
System.out.println("Executing....");
}
@Test void testExecute(){execute();}
}

备注接的方法与其他方法没有区别,在这个例子中,注解@Test可以与任何修饰符作用于方法,例如public、static或者void。从语法角度看,注解的使用方式几乎与修饰符使用一模一样。

package littlepage.annotation.test1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}

除了@符号以外,@Test的定义很像一个空的接口。定义注解,你需要一些元注解(meta-annotation),如@Target和@Retention。@Target用来定义你的注解将用于什么地方(例如一个方法或者一个域),@Retention用来定义注解在哪一个级别可用,在源码中(Source),类文件中(Class)或者运行时(Runtime)

在注解中,一般会包含一些元素以某些值。当分析处理注解时,程序或者工具可利用这些值。注解的元素看起来很像接口方法,唯一区别是你可以用为其指定默认值。

没有元素的注解称为标记注解,例如上面的@Test。

下面死一个简单的注解,我们可以使用它来跟踪项目用例。

package littlepage.annotation.test1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
public int id();
public String description() default "no description";
}

注意,id和description类似方法的定义,由于便要一起会对id进行类型检查,因此将用例文档追踪数据库与源代码的关联是可靠的。description元素有一个默认值,如果注解某方法没有给出description的值,那么处理器会使用该元素默认值。

下面一个类中有三个方法被注解的用例

package littlepage.annotation.test1;

import java.util.List;

public class PasswordUtils {
@UseCase(id=,description = "Password must contain at least one numeric")
public boolean validatePassword(String password){
return (password.matches("\\w*\\d\\w*"));
} @UseCase(id=)
public String encryptPassword(String password){
return new StringBuilder(password).reverse().toString();
} @UseCase(id=,description = "New passwords can't equal previously used ones")
public boolean checkForNewPassword(List<String> prevPasswords,String password){
return !prevPasswords.contains(password);
}
}

元注解

Java目前只内置了3种标准注解,以及四种元注解。元注解负责注解其他注解。

图:详见Thinking in Java p622

编写注解处理器

如果没有用来读取注解的工具,那注解也不刽比注释更加有用。使用注解的过程中,很重要的一个部分是创建和使用注解处理器。Java SE5扩展了反射机制的API,帮助程序员构造这类工具。同时,它还提供了一个外部工具apt帮助程序员解析带有注解的Java代码。

下面是一个非常简单的注解处理器,我们将用它来读取PasswordUtils类,并使用反射机制查找@UseCase标记。我们为其提供了一组id值,然后它会列出在PasswordUtils中找到的用例,以及缺失的 用例。

package littlepage.annotation.test1;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; public class UseCaseTracker {
public static void trackUseCases(List<Integer> useCases, Class<?> clazz){
for (Method m:clazz.getDeclaredMethods()) {
UseCase uc = m.getAnnotation(UseCase.class);
if (uc != null) {
System.out.println("Found Use Case:" + uc.id() + " " + uc.description());
useCases.remove(new Integer(uc.id()));
}
}
} public static void main(String[] args) {
List<Integer> useCases=new ArrayList<>();
Collections.addAll(useCases,,,,);
trackUseCases(useCases,PasswordUtils.class);
}
}

这个程序用到了两个反射的方法:getDeclaredMethods()和getAnnotation(),它们都属于AnnotatedElement接口(Class,Method和Field等类都实现了该接口)。getAnnoation()方法返回指定类型的注解对象。在这里就是UseCase。如果被注解方法上没没有该类型的猪价,则返回null值。然后我们通过调用id和description的方法从返回的对象中提取元素的值。

注解元素

标签@UeCase由UseCase.java定义,其中包含int元素id,以及一个String元素description,注解元素可用类型如下所示:

  • 所有基本类型(int,float,boolean等)
  • String
  • Class
  • enum
  • Annotation
  • 以上类型的数组

如果你使用其他类型,那么编译器就会报错。也不允许使用任何包装类型,不过由于自动打包机制,这个算不上限制。注解也可以作为元素类型,稍后,我们可以看到,这是一个很有用的技巧。

(浅识注解,博主学习速度太慢,需要慢慢消化 )

Thinking in Annotation的更多相关文章

  1. Spring Enable annotation – writing a custom Enable annotation

    原文地址:https://www.javacodegeeks.com/2015/04/spring-enable-annotation-writing-a-custom-enable-annotati ...

  2. 【java】细说 JAVA中 标注 注解(annotation)

    Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用 下面我们来详细说说这个注解,到底是怎么一 ...

  3. Java学习之注解Annotation实现原理

    前言: 最近学习了EventBus.BufferKinfe.GreenDao.Retrofit 等优秀开源框架,它们新版本无一另外的都使用到了注解的方式,我们使用在使用的时候也尝到不少好处,基于这种想 ...

  4. Java Annotation概述

    @(Java)[Annotation|Java] Java Annotation概述 用途 编译器的相关信息,如用于检测错误和一些警告 编译时和部署时的处理,如一些软件用于自动生成代码之类的 运行时处 ...

  5. hibernate学习三(使用Annotation,注解)

    一.新建一个工程hibernate_02_HelloWorld_Annotation(复制01工程并重命名); 二.新建一个实体类teacher.java,数据库中新建teacher表; import ...

  6. struts2使用annotation注意事项

    struts2使用annotation注意事项 1.包名只能以.action .actions  .struts  .struts2结尾.如:com.cnbolgs.web.actions 2.类名只 ...

  7. Data Validate 之 Data Annotation

    什么是Data Annotation ? 如何使用 ? 自定义Validate Attribute EF  Db first中使用Data Annotation asp.net MVC中使用Data ...

  8. SpringMvc的xml配置与annotation配置的例子的区别

    1.导入jar包时,要在xml配置基础上加 spring-aop-4.2.2.RELEASE.jar (注解的时候需要) 2.编写controller的时候要annotation需要做相关配置即红色部 ...

  9. spring3.0使用annotation完全代替XML(续)

    从回帖的反应来看,大多数人还是不赞成完全代替XML的,这点倒是在意料之中.我个人还是倾向于用代码来取代XML的Bean定义,当然这更多的是关乎个人偏好,不代表与我观点不同的人就是错的. 先来说说代码相 ...

  10. spring3.0使用annotation完全代替XML(三)

    很久之前写过两篇博客: spring3.0使用annotation完全代替XML spring3.0使用annotation完全代替XML(续) 用java config来代替XML,当时还遗留下一些 ...

随机推荐

  1. shell命令别名

    ~/.bashrc文件 [root@linuxzgf ~]# vi ~/.bashrc            在alias cp='cp -i'前加上"#"注释,重新登录即可实现复 ...

  2. pycharm 调用turtle模块时,窗口闪屏不能显示

    #如下代码时,在pycharm中运行时,窗口在程序结束后,直接关闭,不能看到绘制的图像. #在python自带的IDE中,在执行代码后,可以看到窗口的显示. import turtle t = tur ...

  3. mysql根据身份证查询年龄,地址,性别

    elect  case left(idcard,2)  when '11' then '北京市' when '12' then '天津市' when '13' then '河北省' when '14' ...

  4. 64位 Qt5.12 MySql 连接问题

    关于怎么检查Qt是否带MySql驱动 ,到Qt安装目录下 plugins\sqldrivers下寻找是否有qsqlmysql.dll文件      例如:F:\Qt\Qt5.9.6\5.9.6\msv ...

  5. 从输入url到页面展现的过程

    先看一幅图:(下面的所有图我都进行拉伸压缩了  如果看不到  可以右键复制图片地址 然后到浏览器粘贴查看  不然显示不全图片) mac没有画图软件  不好意思  xmind做的 1. 输入网址   当 ...

  6. Python Module_Socket_网络编程

    目录 目录 Socket 套接字 套接字的原理 套接字的数据处理方式 套接字类型 Socket 标准函数 ServerSocket 标准函数 ClientSocket 标准函数 公有标准函数 Sock ...

  7. 中国MOOC_面向对象程序设计——Java语言_第1周 类与对象_1分数

    第1周编程题 查看帮助 返回   我们在题目说明中给出了一部分代码,你需要在这部分代码的基础上,按照题目说明编写代码,然后将两部分代码一起提交. 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨 ...

  8. java jna 调用windows动态链接库

    import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; import com.sun.j ...

  9. .net core 学习小结之 Cookie-based认证

    在startup中添加授权相关的管道 using System; using System.Collections.Generic; using System.Linq; using System.T ...

  10. [DS+Algo] 004 栈、队列及其代码实现

    1. Stack FILO (FirstInLastOut) 的链表结构 在程序编译环境上使用较多 常用操作 push pop peek is_empty size Python 代码示例 class ...