注解

注解:Annotation,也是一种引用数据类型。编译之后生成class文件。

语法:

[修饰符列表] @interface 注解名{
    属性(可有可无)
}

IDEAZ中可直接生成Annotation:

注解

package com.dh.annotation;

public @interface MyAnnotation {
}

注解可用在类、接口、属性、方法、变量,(也包括注解)等等位置上:

package com.dh.annotation;

@MyAnnotation
public class User {

    @MyAnnotation
    private int age;

    @MyAnnotation
    public User(@MyAnnotation int age) {
        this.age = age;
    }

    @MyAnnotation
    public void show() {
        @MyAnnotation
        String s = "abc";
        System.out.println(s);
    }
}

注解的作用其实就是一个标识作用:即有注解怎么样,没有注解怎么样。

JDK内置注解

在java.lang包下有三个注解:

  • @Deprecated:表示过时。
  • @Overried:出现在方法上,给编译器参考,于运行阶段没有关系。编译器会编译检查该方法是否是重写父类的方法,如果不是会有红色波浪线编译错误。
  • @SuppressWarning(不常用)

@Deprecated

使用:

public class User {

    @Deprecated
    public int age;
}

*效果:使用user类的age属性时,会出现删除线,并且允许会有warnning。

注解

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
    String since() default "";
    boolean forRemoval() default false;
}

@Overried

使用:

package com.dh.annotation;

public class Test {
    @Override
    public String toString() {
        return "重写toString方法";
    }
}
//若不是重写父类的方法会直接编译报错(在此处就不放图片了,可以自行测试)

源码:

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

可以看到Override注解中没有任何的内容,但是其上面又有两个注解。

注解注解的注解叫元注解(中国文化博大精深!),即@Target和@Retention在此处为元注解。

@Target

用来指定注解可以放的位置。ElementType.METHOD代表只能放在方法上。

点开Target的源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();	//ElementType为一个枚举类型
}
//ElementType的属性:(各个属性的意思可以查看api文档)
//TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE,TYPE_PARAMETER,TYPE_USE,MODULE

@Retention

用来指定注解保存的位置。RetentionPolicy.SOURCE表示保存在java源文件中。

点开Retention的源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();	// RetentionPolicy是一个枚举类型
}
//RetentionPolicy的属性:(各个属性的意思可以查看api文档)
//SOURCE,CLASS,RUNTIME

注解属性

上面的注解都有自己的属性。那注解如何书写自己的属性呢?

语法:

类型 属性名()[default 值];//[]可选
//类型可以是8大基本数据类型、String、Class、枚举,及它们的数组。(其余就不行了)
  • 如果注解中有属性,在使用时需要给它们赋值,否则会报错,除非有默认值,有默认值再赋值则会覆盖掉默认值。

格式:@注解(name = value,...,(数组)name = {value1,...}(如果数组中只有一个值,可以省略{})。

  • 如果注解中的属性名是value,并且只有一个,value =可以省略不写,只写属性值。

例:

枚举类:

package com.dh.annotation;

public enum DAY {
    ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN
}

注解类:

package com.dh.annotation;

@Target(ElementType.FIELD)	//只能用于属性上
@Retention(RetentionPolicy.RUNTIME)	//保存到类文件上,并由JVM运行时保存,可以被反射获取到
public @interface MyAnnotation {
    String name();
    int age();
    //有默认值
    double grade() default 100;
    //枚举数组
    DAY[] day();
}

测试类:

package com.dh.annotation;

public class User {

    @MyAnnotation(name = "Tom",age = 18,day = {DAY.FIVE,DAY.SEVEN})
    private int age;
}

利用反射获取注解的属性及属性值

注解类:

package com.dh.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String name();
    int age();
    //有默认值
    double grade() default 100;
    //枚举数组
    DAY[] day();
}

User:

package com.dh.annotation;

public class User {

    @MyAnnotation(name = "Tom",age = 18,day = {DAY.FIVE,DAY.SEVEN})
    @Deprecated
    public int age;
}

测试:

package com.dh.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class Test {
    //为了代码更好看,将异常采取throws方式处理
    public static void main(String[] args) throws Exception {
        //先获取Class对象
        Class c = Class.forName("com.dh.annotation.User");
       //出现在属性上的注解,要先获取属性
        Field age = c.getDeclaredField("age");
        boolean b = age.isAnnotationPresent(MyAnnotation.class);
        System.out.println(b);
        if(b){
            //获取注解
            Annotation[] annotations = age.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }
        }
    }
}

结果:

true
@com.dh.annotation.MyAnnotation(grade=100.0, name="Tom", age=18, day={FIVE, SEVEN})
@java.lang.Deprecated(forRemoval=false, since="")

总结一下,其实也就需要掌握四个常用注解的注解功能,以及如何自定义注解,自定义注解中如何定义属性(可以支持的属性数据类型有哪些),注解可以用在哪里,具体如何使用注解(包括属性的使用)。

上一篇:@interface 自定义注解


下一篇:QT 第24课 布局管理器(三)