Java 注解(Annotation)

1. 自定义注解(Annotation)

Annotation是从JDK 1.5开始,引入的新技术。

注解使用格式:

  • @注解名
  • 后边还可以跟上括号,以添加一些参数值

例如:

public class TestAnnotation {

	// 使用@Override注解,标识此方法重写了父类的方法
	@Override
	public String toString() {
		// ...
	}
}

在哪里使用?

  • 可以附加在package、class、method、field等上面,相当于给它们添加了额外的辅助信息
  • 可以通过反射机制,编程实现对这些元数据(注解)的访问

内置注解:

Java中内置了3个注解(如前面的@Override就是一个内置注解),它们的作用如下所示:

  • @Override:表示一个方法重写了其父类的方法
  • @Deprecated:表示其修饰的内容不被推荐使用
  • @SuppressWarnings(...):抑制编译时的警告信息,需要在括号中填入参数

元注解(meta-annotation,负责注解其它注解,自定义注解时使用):

元注解的作用是解释其它自定义的注解,也就是说,我们在自定义实现注解时,可以通过元注解对自定义注解的一些属性(如注解作用在哪、注解的生命周期等)进行限定。

JDK 1.5 定义了4个标准的元注解类型:

  • @Target:描述注解的使用范围(用在什么地方,如类上、方法上 …)
  • @Retention:用于表述注解的生命周期(在什么地方有效,通常为RUNTIME)
    • SOURCE:注解在源文件中有效,将被编译器丢弃
    • CLASS:注解在class文件中有效,将被JVM丢弃
    • RUNTIME:注解在运行时有效,可以通过反射读取器信息
  • @Documented:用于标记在生成javadoc时是否将注解包含进去
  • @Inherited:如果在注解上标记了@Inherited,则说明子类可以继承父类中的该注解

自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口。

  • 格式:public @interface 注解名 { 内容 }

  • 其中的每一个方法实际上是在声明一个配置参数

    • 格式:参数类型 参数名();

    • 方法名称就是参数的名称

    • 返回值类型就是参数的类型(只能是基本类型、Class、String、emun)

  • 可以通过default来声明参数的默认值

  • 如果只有一个参数成员,一般参数名为value(这样的话在使用时可以直接传入参数,无需特别指明value = "..."

  • 注解元素必须要有值,在定义注解元素时,常使用空字符串、0作为默认值

示例:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface TestAnnotation {
    String value();
    int[] array();
}

2. 利用Reflection操作注解

自定义注解:

为了方便举例,这里模拟自定义了两个数据库表的注解,分别用于标识表和表中的列的信息。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DatabaseClass {
    String value(); // 表名
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DatabaseField {
    String columnName(); // 列名
    String type(); // 类型
    int length(); // 长度
}

在User类上增加注解:

有了前面自定义的两个注解,就可以对数据库表的对应类进行相应的标识。

@DatabaseClass("database_user")
public class User {
    @DatabaseField(columnName = "id", type = "int", length = 11)
    private int id;
    @DatabaseField(columnName = "user_name", type = "String", length = 30)
    private String userName;
    @DatabaseField(columnName = "password", type = "String", length = 30)
    private String password;

    // ...
}

利用Reflection获取注解信息:

在用注解标识了相应的类之后,我们该如何获取这些“标识信息”呢?答案当然是:通过反射(Reflection)

public class ReflectionAnnotation {

    public static void main(String[] args) throws NoSuchFieldException {
        User user = new User();
        Class userClass = user.getClass();
        // 获取类上所有的注解
        System.out.println("获取类上所有的注解:");
        Annotation[] annotations = userClass.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        // 获得类上指定注解的值
        System.out.println("获得类上指定注解的值:");
        DatabaseClass databaseClass = (DatabaseClass) userClass.getAnnotation(DatabaseClass.class);
        String databaseClassValue = databaseClass.value();
        System.out.println(databaseClassValue);

        // 获得字段上指定注解的值
        System.out.println("获得字段上指定注解的值:");
        Field id = userClass.getDeclaredField("userName");
        DatabaseField databaseFieldValues = id.getAnnotation(DatabaseField.class);
        System.out.println(databaseFieldValues.columnName());
        System.out.println(databaseFieldValues.type());
        System.out.println(databaseFieldValues.length());
    }
}

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值