Annotation概述

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

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

基本Annotation

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

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

<code class="hljs" java="">public class Fruit {
    public void info(){
        System.out.println(这是一个水果,想吃吗?);
    }
}
public class Apple extends Fruit {
    @Override
    public void info() {
        System.out.println(这不仅是一个水果,它是苹果.);
    }
}
</code>
如果Apple类的info()方法名写成了inf()的话,编译器会报错。值得注意的是,@Override只能修饰方法,不能修饰其他程序元素。

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

<code class="hljs" cs="">public class Fruit {
    @Deprecated
    public void info(){
        System.out.println(这是一个水果,想吃吗?);
    }
}
public class DeprecatedTest {
    public static void main(String[] args) {
        // 使用info()方法时将会出现划线,表示该方法已过时.
        new Fruit().info();
    }
}
</code>
@SuppressWarnings:抑制编译器警告。@SuppressWarnings表示被该Annotation修饰的代码取消显示指定的编译器警告。

<code class="hljs" cs="">public class SuppressWarningsTest {
    public static void main(String[] args) {
        @SuppressWarnings(rawtypes)
        /*
         * List集合在定义时,没有指定泛型类型.
         *  * 默认情况下,出现编译器警告.
         *  * 使用@SuppressWarnings注释后,取消警告信息.
         */
        List list = new ArrayList();
    }
}
</code>
自定义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只能修饰成员变量。 E
lementType.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
}
</code>
@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
}
</code>
反射读取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(ClassannotationClass)
实际获取某类使用的Annotation信息的方式如下:

public class AnnotatedElementTest {
    public static void main(String[] args) throws Exception {
        // 获取对应类的Class对象.
        Class<userinfotest> 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 @interface JDBCInfo {
    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();
    }
}

Annotation概述相关推荐

  1. Spring-AOP @AspectJ切点函数之@annotation()

    文章目录 @annotation()概述 实例 @annotation()概述 @annotation表示标注了某个注解的所有方法. 下面通过一个实例说明@annotation()的用法. Annot ...

  2. java annotation list_[Java5新特性]Annotation注解

    Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annotation就是提供了一种为程序元素设置元数据的方法 ...

  3. 注解(Annotation) 学习笔记(尚硅谷康师傅版)

    注解(Annotation) 一.注解(Annotation)概述 ​ 从JDK 5.0开始, Java 增加了对元数据(MetaData)的支持, 也就是Annotation(注解) ​ Annot ...

  4. Java基础3-枚举类与注解

    Java 枚举类 一.枚举类的使用 1.枚举类的理解:类的对象只有有限个,确定的.我们称此类为枚举类. 2.当需要定义一组常量时,强烈建议使用枚举类. 3.如果枚举类中只有一个对象,则可以作为单例模式 ...

  5. 枚举类与注解的详细介绍

    目录 枚举类的使用 自定义枚举类  : 使用enum定义枚举类 Enum类的主要方法 实现接口的枚举类 注解 注解 (Annotation) 概述 常见的Annotation示例 示例二:在编译时进行 ...

  6. Java基础学习——第十章 枚举类注解

    Java基础学习--第十章 枚举类&注解 一.枚举类(enum) 1. 枚举类的概念 枚举类:类的对象只有有限个,确定的 线程状态:创建.就绪.运行.阻塞.死亡 当需要定义一组常量时,强烈建议 ...

  7. JavsSE内容全链接

    JavsSE内容全链接 JavaSE语言概述 JavaSE基本语法上 JavaSE基本语法下 JavaSE数组 JavaSE面向对象编程上 JavaSE面向对象编程中 JavaSE面向对象编程下 Ja ...

  8. Java基础加强-(注解,动态代理,类加载器,servlet3.0新特性)

    1.   Annotation注解 1.1.  Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annota ...

  9. Annotation(注解)概述

    从JDK1.5开始, Java增加了对元数据(MetaData)的支持,也就是 Annotation(注解). Annotation其实就是代码里的特殊标记,它用于替代配置文件,也就是说,传统方式通过 ...

最新文章

  1. 正弦信号有效值 c语言,推导正弦波正弦量、平均值、有效值基本公式
  2. Flask的上下文管理机制
  3. Docker入门到实践
  4. 陈旸:清华博士的模型信仰
  5. 2015 多校赛 第三场 1002 (hdu 5317)
  6. 从输入url到页面加载完成发生了什么
  7. java开发就业困难吗_就业困难期,他们面临着幸福的烦恼
  8. 案例5-条件查询商品
  9. CAN Ape 标定与诊断
  10. 计算机编程php网页源码水果网上销售系统mysql数据库web结构html布局
  11. 计算机网络的功能分类,计算机网络的功能与分类
  12. 设置用户计算机的ip地址,电脑动态IP地址怎么设置
  13. 冰封王座人工只能_魔兽争霸3玩家热议 人工智能能否轻松战war3胜职业选手?
  14. Android实现一键开启自由窗口、分屏、画中画模式——画中画模式
  15. MySQL 为日期增加一个时间间隔
  16. 深度学习 场景识别_使用深度学习进行自然场景识别
  17. 多米诺骨牌问题Push Dominoes
  18. 【ESD专题】如何审查TVS管的数据手册
  19. Java内容整理回顾——第一回 小卷入坑记
  20. 网络安全 基础之 Windows漏洞复现(MS12-020)死亡蓝屏

热门文章

  1. oa办公系统与档案管理系统成功对接
  2. jiraAPI调用403问题,返回XSRF check failed
  3. 学习计划(12.10前)
  4. latex (加粗方法)
  5. Diablo世界观与剧情综合说明
  6. JavaScript递归(空瓶子换酒)
  7. 那个从深圳流水线工人去Google上班程序媛,最近失业了!
  8. 数学建模——欧拉算法(求解常微分方程)
  9. ui自动化里面通过.text获取文本值进行断言【杭州多测师】【杭州多测师_王sir】...
  10. Mac电脑上最好的3个mobi阅读器