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. Oracle与MySQL的概念区别

    MySQL MySQL是一个以用户为中心的概念,一个用户下,拥有多个数据库,一个数据库下拥有多个数据库表!然而Oracle与MySQL有很大的不同!! Oracle Oracle中,一个数据库拥有多个 ...

  2. 关闭layer.open打开的页面

    window.parent.location.reload(); //刷新父页面 var index = parent.layer.getFrameIndex(window.name); //获取窗口 ...

  3. 阶段3 1.Mybatis_11.Mybatis的缓存_5 缓存的概念

    2.Mybatis中的缓存     什么是缓存         存在于内存中的临时数据.     为什么使用缓存         减少和数据库的交互次数,提高执行效率.     什么样的数据能使用缓存 ...

  4. 使用cesium中的scene.open中遇到的几个问题

    有些服务是发在场景(scene)下的,超图提供了一个很方便的方法:scene.open,这个方法会将场景中所有的图层(无论是OSGB还是影像和地形)加载进来.同时这个方法会自带一个自动地位功能,具体实 ...

  5. Gradle之Gradle 的基本使用(一)

    [Android 修炼手册]Gradle 篇 -- Gradle 的基本使用 预备知识 基本的 android 开发知识 了解 Android Studio 基本使用 看完本文可以达到什么程度 掌握 ...

  6. ReportManager

    package com.neusoft.report.engine; import com.neusoft.report.common.Logger; import com.neusoft.repor ...

  7. 机器学习实战-Logistics回归

    Logistics回归:实战,有两个特征X0,X1.100个样本,进行Logistics回归 1.导入数据 def load_data_set(): """ 加载数据集 ...

  8. Pytorch搭建卷积神经网络用于MNIST分类

    import torch from torch.utils.data import DataLoader from torchvision import datasets from torchvisi ...

  9. 20191118 Spring Boot官方文档学习(4.9)

    4.9.安全 如果Spring Security在类路径上,则默认情况下Web应用程序是采用的.Spring Boot依靠Spring Security的内容协商策略来确定使用httpBasic还是f ...

  10. 只需要2个工具,百度云盘大文件就能用迅雷和IDM下载

    不会代码,不懂脚本,没关系 ,能找到一座通往它们的桥梁,照样能到达彼岸. 这里以360极速浏览器为例. 在浏览器地址框输入以下地址直接到达浏览器安装扩展插件的地方(偷个懒,复制网址吧),https:/ ...