继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Java注解

Michaelix
关注TA
已关注
手记 2
粉丝 12
获赞 463
概述

Java注解在1.5版本的时候推出,很多优秀的框架都支持注解模式的配置,比如 Spring 等。本文介绍注解相关的定义,以及自定义注解的方法。

注解的基本概念

注解(Annotation)提供了一种关联信息以及元数据的途径和方法。是一个接口,程序可以通过反射来获取指定程序元素中的 Annotation 对象,然后通过解析 Annotation 对象获取注解中的元数据。可以应用于包、类型、构造方法、方法、成员变量、参数、局部变量等等的声明中。在注解中以"name = value"的形式存储。

Annotation 不能影响程序代码的执行,尽管一些注解通过反射技术可以在运行时被访问,但是java的语言解释器在工作时是忽略他们的。

注解的分类:

  • 标记注解: 没有成员定义的注解类型称为标记注解,用于提供给我们某种信息;
  • 单值注解: 注解中只有一个元素,元素的名称为value,可以写成 @annotation(value)的形式,省略 name,其中 value 就是注解value元素对应的值。
  • 完整注解:
元注解

所谓元注解即是注解的注解,用来负责对其他注解进行注解。
Java5提供了4个标准的元注解(meta-annotation)类型:

  • @Target

    • 含义: 指定注解修饰的对象的范围,通俗的讲就是注解使用的时候要放在哪里(方法上,类上等等)
    • 取值(ElementType):
      1. CONSTRUCTOR: 描述构造器
      2. FIELD: 描述域属性
      3. LOCAL_VARIABLE: 描述局部变量
      4. METHOD: 描述方法
      5. PACKAGE: 描述包
      6. PARAMETER: 描述参数
      7. TYPE: 描述类、接口或注解、枚举类型 enum
  • @Retention

    • 含义: 定义注解保留的时长,限制注解的生命周期。
    • 取值(RetentionPolicy):
      1. SOURCE: 源文件保留,被编译器所丢弃
      2. CLASS: 在字节码文件(*.class)中保留,被JVM所丢弃
      3. RUNTIME: 在运行时保留
  • @Inherited

    • 含义: 被标注的类型是被继承的,使用 @Inherited 修饰的类型作用于一个 class 上时,那么注解也将应用在该 class 的子类。
  • @Documented
    • 含义: 可以使用 javadoc 工具进行文档化操作。
自定义注解

使用 @interface 自定义注解的时,继承 java.lang.annotation.Annotation 接口。被定义的注解不能再继承其他的注解或接口。注解中的每一个方法实际上相当于声明配置参数。其中方法的名称就是参数的名称,方法不能有任何的参数和 throws 语句,方法的返回值就是参数的类型(返回值类型只能是基本数据类型、Class、String、enum、Annotation),同时可以使用default关键字来声明参数的默认值。

注解的参数设置:

  • 使用 public 和默认(default)权限修饰符;
  • 参数成员只能使用八种基本数据类型以及 String、Class、Enum、Annotation 以及相应的数组型;
  • 如果注解中只含有一个参数,建议设置为 value();
  • 使用 default 关键字可以指定注解元素的默认值。注解要求定义的元素必须有确定的值,因此要么在注解的默认值中指定,要么在使用注解的时候指定。非基本数据类型的值不允许是 null。因此,经常使用空字符串(Void.class)或者0来作为默认值。也可以使用负数或空字符串来表示某个元素不存在。

示例:

/**
 * 自定义注解示例代码
 *
 * @author Michal
 * @create 2016-04-19 15:39
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {

    /**
     * 数据库表名
     */
    String value();
}
/**
 * 自定义注解示例代码
 *
 * @author Michal
 * @create 2016-04-19 15:42
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {

    /**
     * 数据库的列名
     *
     * @return
     */
    String column() default "";

    /**
     * 数据类型
     *
     * @return
     */
    String type() default  "";

    /**
     * 数据大小
     *
     * @return
     */
    int length() default 0;
}
注解解析器

注解并不会影响代码的运行,因此必须配合解析器使用,否则注解和注释也没什么具体的区别了。使用Java反射API中的 AnnotatedElement 接口可以方便进行注解的解析。

/**
 * 注解解析器
 *
 * @author Michal
 * @create 2016-04-19 15:58
 */
public class AnnotationUtil {

    public static void parse(Class<?> target) {
        Table table = target.getAnnotation(Table.class);
        System.out.println("数据库表名: " + table.value());

        Field[] fields = target.getDeclaredFields();
        for (Field f : fields) {
            Column column = f.getAnnotation(Column.class);
            System.out.println("列名: " + column.column() + ", 数据类型: " + column.type() + ", 数据大小: " + column.length());
        }
    }

}
/**
 * @author Michal
 * @create 2016-04-19 16:15
 */
public class Main {
    public static void main(String[] args) {
        AnnotationUtil.parse(TableTest.class);
    }
}

@Table("测试表")
class TableTest {
    @Column(column = "名字", type = "java.lang.String", length = 12)
    private String name;
    @Column(column = "年龄", type = "int", length = 12)
    private int age;
    @Column(column = "地址", type = "String")
    private String address;
}

运行结果:

数据库表名: 测试表
列名: 名字, 数据类型: java.lang.String, 数据大小: 12
列名: 年龄, 数据类型: int, 数据大小: 12
列名: 地址, 数据类型: String, 数据大小: 0
打开App,阅读手记
80人推荐
发表评论
随时随地看视频慕课网APP

热门评论

mark

查看全部评论