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. DAY 1模拟赛

    DAY1 杨溢鑫小姐姐出题 好毒瘤啊 T1 低仿机器人 (robo,1s,64M) 题目描述 自从 Dji 推出 robomaster S1 机器人过后,小文就一直缠着爸爸想要一个机器人.没想到爸爸最 ...

  2. VGA接口一根针折了

    注意!!要由 针 对照着 接口 看!!别看反了! VGA接头图如下: VGA接口,15根针,其对应接口定义如下: 1红基色 red 2 绿基色 green 3 蓝基色 blue 4 地址码 ID Bi ...

  3. Delphi回车键切换焦点

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  4. P站图片下载工具。

    下载 Pixiv 的图片比较麻烦,就做了这么个东西. 主要就是用 HttpWebRequest HttpWebResponse 下载了网页的 html 代码然后截取里面的内容.代码上传到了文件里. p ...

  5. 【HANA系列】SAP HANA 2.0简介

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA 2.0简介   ...

  6. 【MM系列】SAP MM模块-打开前面物料账期的方法

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]在SAP里查看数据的方法   前言部 ...

  7. PL/SQL基本操作

    1.常规过程化形式 declare o_booking_flag ); begin -- Call the procedure destine_ticket(', , 'E', , o_booking ...

  8. centos7 安装redis 出现cc: command not found错误解决

    安装过程 1. 下载并解压 cd /root/software wget http://download.redis.io/releases/redis-3.2.4.tar.gz tar -zxvf ...

  9. Debian/Ubuntu下安装Apache的Mod_Rewrite模块的步骤分享

    启用 Mod_rewrite 模块:sudo a2enmod rewrite 另外,也可以通过将 /etc/apache2/mods-available/rewrite.load 连接到 /etc/a ...

  10. 针对Vue相同路由不同参数的刷新问题

    在使用vue和vue-router开发spa应用时,我们会遇到这样一种问题.当页面跳转时,组件本身并没有发生改变: // 路由映射关系'/form/:type' // 当前页面路由/form/shop ...