java注解

一、概述

注解(Annotation)是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。可以向修饰符一样被使用,用于修饰包,类,构造器,方法,成员变量,参数,局部变量的声明。

二、jdk内置三大注解

       @Override:声明在方法上,表示该方法是重写方法。
       @Deprecated:声明在类,方法,字段等结构上,表示已过时,不推荐使用
       @SuppressWarnings():表示忽略警告

这三种注解都是编译时校验

三、如何自定义注解

参考如下@SuppressWarnings()的定义方式:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {

    String[] value();
}

1.注解声明为:@interface

2.内部定义成员,以方法的方式定义成员,方法返回值表示成员类型,方法名表示成员名(一般使用value),可接受的成员类型只有8种:String,Class,enum类型,Annotation类型,以及他们的数组类型。

3.可以指定成员的默认值,如:String value() default "hello";

4.如果注解没有成员,表示为一个标识作用

5.如果注解有成员,且没有定义默认值,则使用时需要指定成员值。如:@SuppressWarnings("unused"),可以忽略“结构未使用”警告

4.jdk提供的四种元注解 

        作用:jdk中的元注解用于修饰其他注解定义,对其进行解释说明

        四种元注解:

        Retentio     Target     Documented    Inherited

        常用的两个元注解(见下文): Retentio     Target

        不常用的两个元注解:

                 Documented :用于指定被该元注解修饰的注解将被javadoc工具提取成文档,默认情况下,javadoc是不包含注解的。(定义为Document的注解必须设置Rententio值为runtime)

                  Inherited:被他修饰的注解具有继承性,如果某个类使用了被Inherited修饰的注解,则其子类将自动具有该注解。

4.1Retentio

 作用:用于指定被修饰注解的声明周期:

 源码:

public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

 其中RetentionPolicy是一个枚举类:

public enum RetentionPolicy {
    //编译后不会保留到.class文件中
    SOURCE,

    //编译后会保留到.class文件中,但不会加载到内存。
    CLASS,

    //编译后会保留到.class文件中,且会被加载到内存运行。
    RUNTIME
}

举例:注解Override和SuppressWarnings都被@Retention(RetentionPolicy.SOURCE)元注解修饰。注意:如果没有被Rentention修饰,则默认值为RetentionPolicy.CLASS

4.2 Target    

        作用:用户指明被修饰的注解能修饰哪些程序元素。

源码:

public @interface Target {
    //一个枚举数组
    ElementType[] value();
}

ElementType是一个枚举类:

public enum ElementType {
    //class,interface,enum
    TYPE,

    //属性
    FIELD,

    //方法
    METHOD,

    //参数
    PARAMETER,

    //构造器
    CONSTRUCTOR,

    //局部变量
    LOCAL_VARIABLE,

    //注解类型
    ANNOTATION_TYPE,

    //包
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

举例:四种元注解只能修饰注解,所以四种元注解都被@Target(ElementType.ANNOTATION_TYPE)修饰。(通过查看源码可以验证),注意:没有指定则没有要求,哪里都能用。

5.自定义注解类并通过反射获取注解信息



import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class MyAnnotationTest {
    @Test
    public void test(){
        Class<Student> studentClass = Student.class;
        //获得Student类的注解
        Annotation[] annotations = studentClass.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}

//自定义注解
@Inherited  //继承性
@Retention(RetentionPolicy.RUNTIME) //注解会被加载到内存中
@interface MyAnnotation {
    String value();
}

//使用自定义注解
@MyAnnotation("hello")
class Person{

}
//子类会继承注解
class Student extends Person{

}

结果:

6.jdk8中的注解新特性之可重复注解

如果在一个结构上使用多个相同的注解会报错。

如果非要这样做,那么

jdk8以前,可以定义一个注解,里面的元素为指定注解类型的数组,这样使用该注解时,可以给值赋值多个注解,达到了在一个结构上使用多个相同注解的需求。如:

@interface MyAnnotations{
    MyAnnotation[] value();
}
@interface MyAnnotation{
    String value();
}

//达到使用多个MyAnnotation注解的效果
@MyAnnotations({@MyAnnotation("hello"),@MyAnnotation("world")})
class Person{

}

jdk8以后有一个新的元注解@Repeatable:

源代码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    /**
     * Indicates the <em>containing annotation type</em> for the
     * repeatable annotation type.
     * @return the containing annotation type
     */
    Class<? extends Annotation> value(); 
}

使用方法:

@interface MyAnnotations{
    MyAnnotation[] value();
}

@Repeatable(MyAnnotations.class) //将MyAnnotation和MyAnnotataions进行绑定
@interface MyAnnotation{
    String value();
}

//可以直接写多个被Repeatable修饰的相同的注解
@MyAnnotation("hello")
@MyAnnotation("world")
class Person{

}

注意点:

1.MyAnnotation和 MyAnnotations两个注解的target,和Retention要一致。

2.MyAnnotation和MyAnnotations两个注解有没有Inherited要一致

7.jdk8中的注解新特性之类型注解

jdk8之后@Target的属性值ElementType中多了两个类型:TYPE_PARAMETER,TYPE_USE

第一个表示可以修饰在泛型的符号里,第二个表示可以修饰在任何类型上

代码举例:

@Target({ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})
@interface MyAnnotation{
    String value() default "";
}

class Person<@MyAnnotation T>{
    public <@MyAnnotation K> void method( K value){
        @MyAnnotation int a=1;
        System.out.println("method");
    }
}


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值