注解

注解

注解其实就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相对应的处理

传统的方式,我们是通过配置文件(xml文件)来告诉类是如何运行的

有了注解技术以后,我们就可以通过注解告诉类如何运行

在JDK中注解分为了

  • 基本Annotation:在lang包下,用于常用于标记该方法,抑制编译器警告等

  • 元Annotaion:在annotaion包下,常用于修饰其他的Annotation定义

基本注解

  • @Override 重写

  • @Deprecated 过时,该注解也非常常见,Java在设计的时候,可能觉得某些方法设计得不好,为了兼容以前的程序,是不能直接把它抛弃的,于是就设置它为过时

  • @SuppressWarnings 抑制编译器警告,可以用它来让编译器不给予我们警告,当我们在使用集合的时候,如果没有指定泛型,那么会提示安全检查的警告

  • @SafeVarargs "堆污染"警告当把一个不是泛型的集合赋值给一个带泛型的集合的时候,这种情况就很容易发生堆污染….

  • @FunctionalInterface 指定该接口是函数式接口,用该注解显示指定该接口是一个函数式接口

自定义注解基础

标记Annotation

没有任何成员变量的注解称作为标记注解,@Overried就是一个标记注解

//有点像定义一个接口一样,只不过它多了一个@
public @interface MyAnnotation {

}

元数据Annotation

自定义的注解是可以带成员变量的,定义带成员变量的注解叫做元数据Annotation

public @interface MyAnno {
    //定义成员变量
    String getString();
    int getInt();
    //定义成员变量并设置默认值
    String name() default "tom";
}
  • 在注解中定义成员变量,语法类似于声明方法一样

  • 在注解上定义的成员变量只能是 8中基本类型(byte,boolean,char,short,int,long,float,double,)和 String,Enum,Class,annotation类型,以及这些类型的数组

  • 还有一种特殊的情况,如果注解上只有一个属性,并且属性的名称为value,那么在使用的时候,我们可以不写value,直接赋值给它就行

自定义注解使用

把注解上的信息注入到方法上利用的是反射技术

步骤可分为三部:

  • 反射出该类的方法

  • 通过方法得到注解上具体的信息

  • 将注解上的信息注入到方法上

// 注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    String name();
    int age();
}

//使用注解
public class TestAnno {
    @MyAnno(name = "tom",age = 18)
    public void test1(String name,int age){
        System.out.println(name+","+age);
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class test=TestAnno.class;
        Method method=test.getMethod("test1",String.class,int.class);
        MyAnno anno=method.getAnnotation(MyAnno.class);
        String name=anno.name();
        int age=anno.age();
        TestAnno testAnno= (TestAnno) test.newInstance();
        method.invoke(testAnno,name,age);
    }
}

元注解

元Annotation都是用于修饰其他的Annotation定义

@Retention

@Retention只能用于修饰其他的Annotation,用于指定被修饰的Annotation被保留多长时间。

@Retention 包含了一个RetentionPolicy类型的value变量,所以在使用它的时候,必须要为value成员变量赋值,RetentionPolicy有三个值:SOURCECLASSRUNTIME,对应java文件的三个时期:编译,class,运行。@Retention默认是class

因为@Retention默认是class,而反射是在运行时期来获取信息的。因此前面使用自定义注解时就要设置为RetentionPolicy.RUNTIME

@Target

@Target也是只能用于修饰另外的Annotation它用于指定被修饰的Annotation用于修饰哪些程序单元

@Target是只有一个value成员变量的,该成员变量的值是以下的:TYPE(给一个类型进行注解,比如类、接口、枚举),FIELDMETHODPARAMETER(方法内的参数),CONSTRUCTORLOCAL_VARIABLE(局部变量),ANNOTATION_TYPEPACKAGE

@Documented

@Documented用于指定被该Annotation修饰的Annotation类将被javadoc工具提取成文档

@Inherited

@Inherited也是用来修饰其他的Annotation的,被修饰过的Annotation将具有继承性。。。

例子:

  1. @xxx是我自定义的注解,我现在使用@xxx注解在Base类上使用….

  2. 使用@Inherited修饰@xxx注解

  3. 当有类继承了Base类的时候,该实现类自动拥有@xxx注解

把对象注入到方法、属性中

把对象注入到方法中

  • 得到想要类中注入的属性

  • 得到该属性的对象

  • 得到属性对应的写方法

  • 通过写方法得到注解

  • 获取注解详细的信息

  • 将注解的信息注入到对象上

  • 调用属性写方法,将已填充数据的对象注入到方法中

把对象注入到属性中

  • 得到想要注入的对象属性

  • 通过属性得到注解的信息

  • 通过属性的写方法将注解的信息注入到对象上

  • 最后将对象赋给类

 

 

posted @ 2019-12-09 14:28  hjy1995  阅读(120)  评论(0编辑  收藏  举报