注解

作者: 仿若尘土 | 来源:发表于2019-03-11 14:32 被阅读0次

[TOC]

1. 定义

注解相当于一种标记,可加载包、类、属性、方法、方法参数和局部变量上,对程序执行没有影响。编译器、程序等可通过反射获取注解,做相应的处理(如生成SQL语句等)。Java 5开始引入。Java自带的注解包括:

  • @Override:实现/重写父类方法
  • @SuppressWarnings:忽略编译器警告
  • @SafeVarargs:参数安全注解,Java 1.7 加入
  • @Deprecated:废弃注解
  • @FunctionalInterface:函数式接口注解,Java 8加入
    简单的栗子:
// 注解定义
public @interface TestAnnotation{}

// 注解使用
@TestAnnotation
public class Test{}

2. 元注解

可加在注解上的注解,包括@Retention、@Documented、@Target、@Inherited、@Repeatable 5 种,也可自定义元注解,只要@Target包含ElementType.ANNOTATION_TYPE。

2.1 @Retention

注解的声明周期,定义在RetentionPolicy枚举类中,包括RetentionPolicy.SOURCERetentionPolicy.CLASSRetentionPolicy.RUNTIME

  • RetentionPolicy.SOURCE:只有源代码期间保留,编译器编译时丢弃
  • RetentionPolicy.CLASS:保留到编译器,加载到JVM时会被丢弃
  • RetentionPolicy.RUNTIME:可加载到JVM中,运行时可通过反射获取注解信息

2.1 @Documented

生成Javadoc时,包含@Documented注解的元素

2.2 @Target

可添加注解的位置,定义在ElementType枚举类中。

  • ElementType.TYPE:class、接口(包括注解)、枚举
  • ElementType.FIELD:属性
  • ElementType.METHOD:方法
  • ElementType.PARAMETER:参数
  • ElementType.CONSTRUCTOR:构造方法
  • ElementType.LOCAL_VARIABLE:局部变量
  • ElementType.ANNOTATION_TYPE:注解
  • ElementType.PACKAGE:包
  • ElementType.TYPE_PARAMETER:用在类型参数上,如:
// 注解定义
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestTypeParam {}

// 注解使用
public class AnnotationTypeParameter<@TestTypeParam T> {}
// 会报错!!!!!
@TestTypeParam
int i = 1;
  • ElementType.TYPE_USE:标注各种类型,如:
// 注解定义
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestUse {}
// 注解使用
@TestUse
int i;
// 会报错!!!!!
@TestUse
i = 1;

2.3 @Inherited

父类的注解是否可被子类继承,如:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}
@Test
public class A {}
public class B extends A {}

子类B继承了父类A的注解。

2.4 @Repeatable

Java 1.8 加入,可重复添加多个注解,如:

@interface Persons {
    Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
    String role default "";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{}

3. 注解属性

也叫成员变量

public enum AnnotationEnum {
    Enum1(1),
    ENUM2(2),
    ;
    private int id;
    AnnotationEnum(int id) {
        this.id = id;
    }
}

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface MetaAnnotation {
    // 成员变量
    String value();
}

// 生命周期 SOURCE:源文件阶段 CLASS:编译器 RUNTIME:运行期
@Retention(RetentionPolicy.RUNTIME)
// 决定可添加注解的位置 见 ElementType
@Target({ElementType.FIELD,ElementType.TYPE})
public @interface MyAnnotation {
    /**
     * 定义基本属性
     * @return
     */
    // 不设置默认值
    int id();
    // 设置默认值
    String name() default ""; // 设置默认值
    // 数组
    int[] intArr() default {};
    // 枚举类型
    AnnotationEnum enumTest() default AnnotationEnum.Enum1;
    // 注解属性
    MetaAnnotation annotationValue() default @MetaAnnotation("annotationValue");
}

@MyAnnotation(id = 1, name = "test", intArr = {1, 2}, enumTest = AnnotationEnum.ENUM2, annotationValue = @MetaAnnotation("myAnnotationTest"))
public class MyAnnotationTest {
    @MyAnnotation(id = 10)
    public int id;
    // @MyAnnotation 会报错
    public int getId() {
        return id;
    }
    public static void main(String[] args) {
        // Class对象中有处理注解的两个常用方法
        if (MyAnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation annotation = MyAnnotationTest.class.getAnnotation(MyAnnotation.class);
            System.out.println("MyAnnotation.toString: " + annotation);
            System.out.println("int类型:" + annotation.id());
            System.out.println("Sring烈性" + annotation.name());
            System.out.println("int数组: " + annotation.intArr());
            System.out.println("枚举类型:" + annotation.enumTest());
            System.out.println("注解类型:" + annotation.annotationValue());
        }
        Annotation annotation1 = MyAnnotation.class.getAnnotation(MetaAnnotation.class);
        System.out.println("MetaAnnotation.toString:" + annotation1);
    }
}

/*
result:
int类型:1
Sring烈性test
int数组: [I@6fadae5d
枚举类型:ENUM2
注解类型:@javastudy.annotation.MetaAnnotation(value=myAnnotationTest)
MetaAnnotation.toString:null
*/

4. Class对象中和注解相关的方法

  • isAnnotationPresent:判断是否是注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
  • getAnnotation:获取指定注解,如果无该注解,则返回空
 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
  • getAnnotations:获取所有注解
public Annotation[] getAnnotations() {}

栗子见 第3章

5. 应用实例

根据Bean生成SQL语句:

/**
 * table注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
    String value();
}

/**
 * 字段注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
    String value();
}

/**
 * 学生表对应的实例
 */
@Table("test_table")
public class StudentTable {
    @Column("_id")
    private int id;
    @Column("studentName")
    private String name;
    @Column("sex")
    private int sex;

    // 未加注解,不会生成SQL语句
    private String noColumnTest;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSex() {
        return sex;
    }
    public void setSex(int sex) {
        this.sex = sex;
    }
    public String getNoColumnTest() {
        return noColumnTest;
    }
    public void setNoColumnTest(String noColumnTest) {
        this.noColumnTest = noColumnTest;
    }
}

/**
 * 生成SQL语句的工具类
 */
public class SqlProduct {
    public static String selectSql(Object object) {
        Table table = object.getClass().getAnnotation(Table.class);
        // 没有table注解,则直接返回null
        if (null == table) {
            return null;
        }
        // 获取表名
        String tableName = table.value();
        // SQL语句
        String sql = "select * from " + tableName + "where 1 =1 ";
        // 获取属性名
        Field[] fields = object.getClass().getDeclaredFields();
        if (null == fields || 0 == fields.length) {
            return sql;
        }
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            if (null == column) {
                continue;
            }
            // 获取getter方法
            String fieldName = field.getName();
            String getMethodStr = "get" + field.getName().substring(0, 1).toUpperCase() + fieldName.substring(1);
            try {
                Method getMethod = object.getClass().getMethod(getMethodStr);
                Object columnVal = getMethod.invoke(object);
                sql += " and " + column.value() + " = " + columnVal;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return sql;
    }
}

/**
 * 生成SQL
 */
public class Client {
    public static void main(String[] args) {
        StudentTable studentTable = new StudentTable();
        studentTable.setId(1);
        studentTable.setName("xiaocui");
        studentTable.setSex(1);
        studentTable.setNoColumnTest("test");
        String sql = SqlProduct.selectSql(studentTable);
        System.out.println(sql);
    }
}

/*
result:
select * from test_tablewhere 1 =1 and _id = 1 and studentName = xiaocui and sex = 1
*/

6. 参考

  1. Java注解全面解析
  2. 秒懂,Java 注解 (Annotation)你可以这样学
  3. Java基础加强总结(一)——注解(Annotation)

相关文章

  • 注解学习笔记

    什么是注解注解分类注解作用分类 元注解 Java内置注解 自定义注解自定义注解实现及使用编译时注解注解处理器注解处...

  • 注解与反射

    注解 声明一个注解类型 元注解 在定义注解时,注解类也能够使用其他的注解声明。对注解类型进行注解的注解类,我们称之...

  • 1.8 Java 注解annotation

    1.1 注解声明 Java注解Annotation,有声明注解和元注解 元注解:Java提供的元注解,所谓元注解就...

  • 注解的使用

    元注解 注解 注解本质就是接口: 元注解:修饰注解的注解 自定义注解 Text.java FruitName.ja...

  • 注解

    Java注解 注解 元注解 自定义注解 元注解:负责注解其他注解 共有4个标准的meta-annotation类型...

  • Spring高级应用之组合注解和元注解

    1.核心概念: 元注解:可以注解在其他注解上的注解;被注解的注解成为组合注解; 2.组合注解的定义步骤 定义组合注...

  • 2016.10.13-关于注解的自定义和注解的解析

    注解可以分为:1、标识性注解(没有成员变量) 2、注解 3、元注解(注解的注解) 1、注解的自定义 自定义注解的格...

  • 自定义注解

    注解分类 1、代码注解2、编译时注解3、运行时注解 注解范例 使用注解的类 注解解析类 注解实战 需求1、有一张用...

  • 【JAVA】注解

    元注解 用来定义、声明注解的注解。 @Inherited注解 使用此注解声明出来的自定义注解,在使用此自定义注解时...

  • Spring Boot常用注解

    注解速览 配置加载相关 Bean 声明注解 Bean 注入注解 SpringMVC 注解 MyBatis 注解 配...

网友评论

      本文标题:注解

      本文链接:https://www.haomeiwen.com/subject/fjfbpqtx.html