Annotation概述

Annotation是JDK 5.0以后提供对元数据的支持,可以在编译、加载和运行时被读取,并执行相应的处理。所谓Annotation就是提供了一种为程序元素设置元数据的方法,可用于修饰包、类、构造器、方法、成员变量、参数和局部变量的声明,这些信息被存储在Annotation的“name=value”对中。

Annotation能被用来为程序元素(类、方法、成员变量等)设置元数据,比如一段代码的作者或者告诉编译器禁止一些特殊的错误,不会影响代码的执行。

基本Annotation

在Java中提供了3个基本Annotation的用法,使用Annotation时要在其前面增加@符号,并把该Annotation当作一个修饰符使用,用于修饰它支持的程序元素。这3个基本Annotation都定义在java.lang包下,可以通过查看API文档来了解。

@Override:限定重写父类方法。@Override就是用来指定方法覆载的,它可以强制一个子类必须覆盖父类的方法。

public class Fruit {

public void info(){

System.out.println("这是一个水果,想吃吗?");

}

}

public class Apple extends Fruit {

@Override

public void info() {

System.out.println("这不仅是一个水果,它是苹果.");

}

}

如果Apple类的info()方法名写成了inf()的话,编译器会报错。值得注意的是,@Override只能修饰方法,不能修饰其他程序元素。

@Deprecated:标示已过时。@Deprecated用于表示某个程序元素已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告。

public class Fruit {

@Deprecated

public void info(){

System.out.println("这是一个水果,想吃吗?");

}

}

public class DeprecatedTest {

public static void main(String[] args) {

// 使用info()方法时将会出现划线,表示该方法已过时.

new Fruit().info();

}

}

@SuppressWarnings:抑制编译器警告。@SuppressWarnings表示被该Annotation修饰的代码取消显示指定的编译器警告。

public class SuppressWarningsTest {

public static void main(String[] args) {

@SuppressWarnings("rawtypes")

/*

* List集合在定义时,没有指定泛型类型.

* * 默认情况下,出现编译器警告.

* * 使用@SuppressWarnings注释后,取消警告信息.

*/

List list = new ArrayList();

}

}

自定义Annotation

自定义一个Annotation类型使用@interface关键字,定义一个新的Annotation类型与定义一个接口非常像(只是多了一个@符号)。

// 自定义一个Annotation类型

public @interface Test {

}

在自定义一个Annotation类型通常可以用于修饰程序中的类、方法、变量、接口等。一般情况下,使用Annotation会在代码之前使用。

// 自定义Annotation类型定义在类上.

@Test

public class AnnotationTest {

// 自定义Annotation类型定义在成员变量上.

@Test

private int i;

// 自定义Annotation类型定义在构造函数上.

@Test

public AnnotationTest(){}

// 自定义Annotation类型定义在方法上.

@Test

// 自定义Annotation类型定义在方法参数上.

public void fun(@Test String str){

// 自定义Annotation类型定义在变量上.

@Test

int z;

}

}

Annotation属性

自定义Annotation不仅可以是这种简单形式,还可以包含成员变量。自定义的Annotation的成员变量以无形参的方法形式来声明,其方法名和返回值定义了该成员变量的名字和类型。

/**

* 自定义带有username和password属性的Annotation

*

*@author 金云龙

*/

public @interface UserInfo {

String username();

String password();

}

使用带有属性的自定义Annotation时,必须使用其属性指定值,否则会报错。

@UserInfo(username="zhangwuji",password="123")

public class UserInfoTest {

}

自定义Annotation不仅可以设置属性,还可以为属性设置默认值,使用default关键字。

/**

* 自定义带有username和password属性的Annotation

* * 为username属性设置默认值.

*@author 金云龙

*/

public @interface UserInfo {

String username() default "zhangwuji";

String password();

}

如果为自定义Annotation的属性设置了默认值,则在使用时可以不为该属性指定值(使用默认值)。也可以在使用该Annotation时为其属性指定值,则默认值不会起作用。

自定义Annotation中具有名为value的属性,在使用该Annotation时如果只使用value属性的话,可以不写属性名直接指定值。

@UserInfo("jiaozhu")

public class UserInfoTest {

}

Annotation的属性类型只能是基本类型、String、Enum、Class及上述类型的一维数组类型。

@Target注解

@Target修饰自定义Annotation,指定该自定义Annotation可以用于修饰哪些程序单元,例如方法、成员变量等。@Target注解包含一个ElementType类型的value属性,该属性值只能是如下几个:

ElementType.ANNOTATION_TYPE:指定该策略的Annotation只能修饰Annotation。

ElementType.CONSTRUCTOR:指定该策略的Annotation只能修饰构造器。

ElementType.FIELD:指定该策略的Annotation只能修饰成员变量。

ElementType.LOCAL_VARIABLE:指定该策略的Annotation只能修饰局部变量。

ElementType.METHOD:指定该策略的Annotation只能修饰方法定义。

ElementType.PACKAGE:指定该策略的Annotation只能修饰包定义。

ElementType.PARAMETER:指定该策略的Annotation只能修饰参数。

ElementType.TYPE:指定该策略的Annotation可以修饰类、接口或枚举定义。

以下是@Target注解的源码和ElementType的源码:

@Target(ElementType.ANNOTATION_TYPE)

public @interface Target {

ElementType[] value();

}

public enum ElementType {

TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE

}

@Retention注解

@Retention修饰自定义Annotation,指定自定义Annotation的生命周期。@Retention包含一个RetentionPolicy类型的value属性,该属性值只能是如下几个:

RetentionPolicy.CLASS:编译器将把Annotation记录在class文件中。当运行Java程序时,JVM不可获取Annotation信息。这时默认值。

RetentionPolicy.RUNTIME:编译器将把Annotation记录在class文件中。当运行Java程序时,JVM也可以获取Annotation信息,程序可以通过反射获取该Annotation信息。

RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器直接丢弃这种Annotation。

以下是@Retention注解的源码和RetentionPolicy的源码:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)

public @interface Retention {

RetentionPolicy value();

}

public enum RetentionPolicy {

SOURCE, CLASS, RUNTIME

}

反射读取Annotation

使用Annotation修饰了类、方法、成员变量等之后,这些Annotation不会自己生效,必须通过相应程序提取并处理Annotation信息。Java提供的Annotation接口是所有注解的父接口,在JDK 5.0新增加AnnotatedElement接口,该接口提供读取运行时Annotation的方法。只有当自定义的Annotation使用了@Retention(RetentionPolicy.RUNTIME)时,该Annotation才会在运行可见,JVM才能读取保存在class文件的Annotation信息。

以下是AnnotatedElement接口提供的方法API:

方法摘要

T

getAnnotation(Class annotationClass)

Annotation[]

getAnnotations()

Annotation[]

getDeclaredAnnotations()

boolean

isAnnotationPresent(Class extends Annotation> annotationClass)

实际获取某类使用的Annotation信息的方式如下:

public class AnnotatedElementTest {

public static void main(String[] args) throws Exception {

// 获取对应类的Class对象.

Class clazz = UserInfoTest.class;

// 获取对应类方法的Method对象.

Method method = clazz.getMethod("fun");

// 获取类上的注解.

UserInfo anno1 = clazz.getAnnotation(UserInfo.class);

// 打印该注解的username属性值.

System.out.println(anno1.username());

// 获取方法上的注解.

UserInfo anno2 = method.getAnnotation(UserInfo.class);

// 打印该注解的username属性值.

System.out.println(anno2.password());

}

}

注解配置JDBC案例

使用JDBC连接MySQL数据库时,需要driverClassName、url、username和password四个参数。而之前的做法是将这四个参数写入一个配置文件,在JDBCUtils工具类中读取配置文件。目前可以将四个参数定义为一个注解,在JDBCUtils工具类中通过反射获取对应注解定义的四个参数内容。具体做法如下:

定义一个Annotation用于定义JDBC连接MySQL数据库所需的四个参数内容。

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)public @interfaceJDBCInfo {

String driverClassName();

String url();

String username();

String password();

}

定义JDBCUtils工具类,使用Annotation配置四个参数内容,并使用反射进行读取。

public class JDBCUtils {

@JDBCInfo(driverClassName = "com.mysql.jdbc.Driver", url = "jdbc:mysql://localhost:3306/jdbc", username = "root", password = "root")

public static Connection getConnection() throws Exception {

// 获取注解修饰目标对应的反射对象.

Method method = JDBCUtils.class.getDeclaredMethod("getConnection");

// 判断是否存在目前注解

if (method.isAnnotationPresent(JDBCInfo.class)) {

// 获取注解信息

JDBCInfo jdbcInfo = method.getAnnotation(JDBCInfo.class);

// 读取注解属性信息

String driverClassName = jdbcInfo.driverClassName();

String url = jdbcInfo.url();

String username = jdbcInfo.username();

String password = jdbcInfo.password();

// Class类加载驱动

Class.forName(driverClassName);

// 返回连接对象

return DriverManager.getConnection(url, username, password);

}

return null;

}

}

编写一个测试类用于测试JDBCUtils工具类是否正确。

public class JDBCTest {

public static void main(String[] args) throws Exception {

Connection conn = JDBCUtils.getConnection();

String sql = "select * from products";

PreparedStatement statement = conn.prepareStatement(sql);

ResultSet rs = statement.executeQuery();

while (rs.next()) {

System.out.println(rs.getString("name") + "," + rs.getDouble("price"));

}

rs.close();

statement.close();

conn.close();

}

}

转载说明:请注明作者和原文链接,谢谢!

java annotation list_[Java5新特性]Annotation注解相关推荐

  1. java5新特性_5分钟了解Java 12 八大新特性

    导读:Java 12 终于发布了,我们一起来看一看 Java 12 中的新特性.通过本文可以在5分钟内快速了解 Java 12 新特性. 1 Switch 表达式 使用Java 12,switch不仅 ...

  2. 【JAVA拾遗】Java8新特性合辑

    [JAVA拾遗]Java8新特性合辑 文章目录 [JAVA拾遗]Java8新特性合辑 0. 逼逼 [--/--]126 Lambda Expressions & Virtual Extensi ...

  3. 详解Java 8十大新特性

    前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with Java ...

  4. java的发展(8-17新特性整理)

    java java的诞生与历史: 简介:Java是一门面向对象的编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征. ...

  5. Java 11 正式发布,新特性解读

    Java 11 正式发布,新特性解读 杨晓峰   2018 年 9 月 26 日 话题:Java语言 & 开发 不知不觉 JDK 11 已经发布了,从 9 开始,JDK 进入了让人学不动的更新 ...

  6. Java基础之Java8 新特性

    hp实训8.19_Java基础之Java8新特性 // 信息展示方法 ,接口中,就可以提供一种实现. 就可以使用这种功能.default void print() {System.out.printl ...

  7. 不停歇的Java即将发布JDK16新特性速览及从菜鸟到架构师[图]

    一.不停歇的Java即将发布JDK16新特性速览 当开发者深陷Java8版本之际,这边下一版本Java16有了最新的消息,与Java15一样,作为短期版本,Oracle仅提供6个月的支持. 根据发布计 ...

  8. 详解 Java 17中的新特性:“密封类”

    作者:程序猿DD 博客:https://blog.didispace.com/ Java 17推出的新特性Sealed Classes经历了2个Preview版本(JDK 15中的JEP 360.JD ...

  9. Java 17 版本的新特性

    Java 17 版本的新特性

最新文章

  1. 三层交换机原理:01路由器如何隔离广播域?
  2. ebpf 学习-bpftrace 语法 入门
  3. java中为什么要用json_Java中使用JSON
  4. 无缓冲channel的内存泄漏问题
  5. 数据结构 - 字符串 - 最长公共子序列 + 最长公共子字符串 - 动态规划
  6. oracle中block
  7. 今天看到头条好多新手说摆摊不挣钱
  8. 让我们深入了解PP YOLO做出的贡献
  9. php中获取随机数的方法,PHP实现获取随机数的方法
  10. javascript如何处理多级的实时监听
  11. SVN下载 1.11.0版本 win7 32位 安装文件及中文语言包
  12. Arduino 水质检测仪(浊度、TDS、温度、电导率、吸光度、硬度)带18b20温度补偿。
  13. python中扑克牌类设计_创建扑克牌类Python
  14. 5328笔记 Advanced ML Chapter1-Introduction to Machine Learning Problems
  15. jq中如何调用vue中的方法
  16. tshark抓包小结
  17. 队列应用----模拟患者看病
  18. 解决极值中的神奇设k法_神奇宝贝Go拥有对您的Google帐户的完全访问权限。 这是解决方法[更新]...
  19. Python - 深度学习系列13- 显卡与CPU计算对比
  20. WINCC V7.5入门实例教程,使用常数数组用FunctionTrendControl控件绘制趋势曲线(区别于7.0及以前的老版本,脚本更新)

热门文章

  1. cv曲线面积的意义_评价标准专题:常见的TP、TN、FP、FN和PR、ROC曲线到底是什么...
  2. win7系统如何连接蓝牙耳机及出现的问题
  3. C#作为上位机,控制PLC的两种方式
  4. Flask 数据库操作出现的低级错误
  5. 聊聊对 BPF 程序至关重要的 vmlinux.h文件
  6. 2021年度鼓励发展商业品牌首店项目申报条件及奖励,补贴500万
  7. 【案例集】直播间“长高产品”翻车了,120升油箱加了161升?
  8. 敏捷中的过程改进实践和工具
  9. Javaweb-书城项目
  10. SAP后台作业debug步骤