Java进阶之注解

来源:互联网 发布:windows loader cw 编辑:程序博客网 时间:2024/06/06 00:52

1 介绍

  Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
这里写图片描述
  

2 注解分类

  注解的语法比较简单,除了@符的使用之外,它基本与Java固有语法一致。JavaSE5内置了三种标准注解:

  • @Override,表示当前的方法定义将覆盖超类中的方法。
  • @Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。
  • @SuppressWarnings,提示编译器或工具软件禁止提示警告信息

    Java还提供了4种注解,专门负责新注解的创建:

    这里写图片描述

3 注解的生命周期

3.1 SOURCE级别

@Override:保证方法能够正确重写,错误会提示。
由源码得到class文件,class里面不需要显示@Override,它的@Retention(RetentionPolicy.SOURCE)是SOURCE(编译)级别,目标是方法@Target(ElementType.METHOD),是注解在方法上面的。

@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {}

3.2 CLASS级别

在java文件编译得到.class文件,在class文件里面任然还存在该注解
比如butterknife中的控件注解,就是CLASS级别。
@ViewInjector(R.id.text)在.class文件中还存在,在加载到虚拟机中就不存在了。只需要在编译时生成辅助类文件,在运行过程中不需要通过反射去读取注解的内容。

@Retention(RetentionPolicy.CLASS)@Target(ElementType.FIELD)public @interface ViewInjector{   int value();}

3.3 RUNTIME级别

当.class文件加载到虚拟机的时候,该注解任然读取的到该注解。

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface ViewInjector{   int value();}

4 实践

(1)定义注解DbTable、DbFiled

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface DbTable {    String value();}
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface DbFiled {    String value();}

(2)注解类UserBean

@DbTable("tb_user")public class UserBean {    @DbFiled("user_name")    public String name;    @DbFiled("user_password")    public String password;}

(3)通过反射机制获取(DbTable)注解元素的值

public synchronized boolean init(Class<T> entity) {    entityClass = entity;    // 通过反射机制获取(DbTable)注解元素的值    if (entity.getAnnotation(DbTable.class) == null) {        // 取类名(user)        tableName = entity.getClass().getSimpleName();    } else {        // 取注解名字(tb_user)        tableName = entity.getAnnotation(DbTable.class).value();    }}

(4)通过反射机制获取(DbFiled)成员变量注解元素的名字

 private void initMappingRelations() {        Cursor cursor = null;        try {            cursor = database.rawQuery(sql, null);            // 数据库表的列名数组            String[] columnNames = cursor.getColumnNames();            // 获取entityClass所有公有的成员变量数组            Field[] variablesFileds = entityClass.getFields();            for (Field filed : variablesFileds) {                filed.setAccessible(true);            }            // 遍历数据库表的列名数组            for (String colmunName : columnNames) {                Field variablesFiled = null;                // 遍历成员变量数组                for (Field field : variablesFileds) {                    String fieldName = null;                    // 通过反射机制获取成员变量注解元素的名字                    if (field.getAnnotation(DbFiled.class) == null) {                        fieldName = field.getName();                    } else {                        fieldName = field.getAnnotation(DbFiled.class).value();                    }                }            }        }     }

5 注意点

  • 当只有value需要设置值的时候(即只有value属性或者其他属性已经制定了default的时候),可以直接不写value,直接在括号里面写值,例如:
    @SuppressWarnings(“deprecation”)
  • 当类型是数组的时候,如果元素只有一个,那么可以省略大括号,直接写一个元素即可。

6 参考文档

java中的注解

JAVA面试-基础加强与巩固:反射、注解、泛型等