欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一篇文章弄懂注解

程序员文章站 2022-07-02 21:50:37
...
注解:注解是附加在代码的一些信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会影响代码的实际逻辑,仅仅起到辅助作用。
注解的三种分类:

1.自定义注解:比如 @Controller,@Service,@Table等等,是开发者定义的注解。
2.元注解:jdk的注解,有四个:@Target,@Inherited ,@Retention,@Documented。
3.内置注解:jdk除了四个元注解之前的注解,如@Override,@SuppressWarnings等

自定义注解:

自定义注解流程:
自定义注解很简单:选择ide,创建annotation取名即可。
一篇文章弄懂注解
然后我们的自定义注解就创建成功啦。

package com.jym.demo.bean;

public @interface MyAnnotation {
}

当然 我们还可以给注解添加属性。注解里定义属性,跟类中的方法类似,需要加括号,如果属性没有默认值,则被注解修饰的类上,必须定义值,否则编译不通过。

package com.jym.demo.bean;

public @interface MyAnnotation {

    // 注解属性
    String name();                        // 被修饰的类必须给name属性赋值,否则会报错
    int age() default 25;                 // 默认值为25
    String hello() default "hello,world"; // 默认值为hello,world
    
}

元注解:

aaa@qq.com:定义了注解的生命周期,注解的生命周期有三个阶段:

@Retention(RetentionPolicy.SOURCE):
注解会保留在源码里,但是编译成class文件后不会出现,即为注解的第一阶段。@Override、@SuppressWarnings都属于这类注解,可以做一些检查性的操作;
@Retention(RetentionPolicy.CLASS):
注解会保留在源码,以及编译后的class文件中,但是不会保留在JVM中,为注解的第二阶段,同样注解也是默认使用这种方式
@Retention(RetentionPolicy.RUNTIME):注解的第三阶段,存在于源码,class文件,以及jvm中,因此我们可以通过反射拿到该注解的信息,我们自定义注解通常使用这种方式,@Deprecated属于此类注解。
具体的反射方式:
注解:

package com.jym.demo.bean;

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

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    // 注解属性
    String name();                        // 被修饰的类必须给name属性赋值,否则会报错
    int age() default 25;                 // 默认值为25
    String hello() default "hello,world"; // 默认值为hello,world

}

被注解修饰的类:

@MyAnnotation(name = "jym")
public class Person {}

测试方法:

    public static void main(String[] args) {
        Class<Person> clazz = Person.class;
        if(clazz.isAnnotationPresent(MyAnnotation.class)){
            MyAnnotation myAnnotation = clazz.getAnnotation(MyAnnotation.class);
            System.out.println(myAnnotation.name()+":"+myAnnotation.age());
        }
    }

结果:

jym:25
2. @Target:设置作用目标,使用范围:

@Target(ElementType.TYPE) :用于接口、类、枚举、注解
@Target(ElementType.FIELD) :字段、枚举的常量
@Target(ElementType.METHOD) :方法
@Target(ElementType.PARAMETER) :方法参数
@Target(ElementType.CONSTRUCTOR) :构造函数
@Target(ElementType.LOCAL_VARIABLE) :局部变量
@Target(ElementType.ANNOTATION_TYPE) :注解
@Target(ElementType.PACKAGE) :包
具体反射流程:
注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {

    // 注解属性
    String name();                        // 被修饰的类必须给name属性赋值,否则会报错
    int age() default 25;                 // 默认值为25
    String hello() default "hello,world"; // 默认值为hello,world

}

修饰类:

public class Person {

    private int age;
    @MyAnnotation(name = "jym")
    private String name;
    private Date birth;
}

测试方法:

    public static void main(String[] args) {
        Class<Person> clazz = Person.class;
        Field[] declaredFields = clazz.getDeclaredFields(); // 获取所有字段
        for (Field declaredField : declaredFields) {
            MyAnnotation annotation = declaredField.getAnnotation(MyAnnotation.class);
            if(annotation!=null){
                System.out.println("姓名:"+annotation.name());
            }
        }

结果:

姓名:jym
3. @Document :

说明该注解将被包含在javadoc中,至于javadoc,就是通过Javadoc技术,从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。需要更多了解的,请百度一下。

4. @Inherited :

继承性,加上这个注解,别的类在继承被该注解修饰的类时,会自动加上这个注解。通过反射也是可以拿到的。

这里说明一下反射的方法:

getFields()方法获得某个类的所有的public的字段,包括父类。getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。同样类似的还有getConstructors()和getDeclaredConstructors(),getMethods()和getDeclaredMethods()。如果感兴趣的,可以在控制台打印一下。

内置注解:

java的一切注解都是基于元注解的
@Override(重写父类方法)
@SuppressWarning(阻止警告)
@FunctionaInterface(指定接口函数式编程)
@SafeVarargs(堆污染警告)
在SpringMVC中,就是通过对controller修饰的类进行反射,将注解里的值存进MAP里,核心servlet才能找到对应的类中的对应方法所执行

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

感谢您的收看,如有哪里写的不对 请留言,谢谢。