zoukankan      html  css  js  c++  java
  • 枚举类与注解 之 注解讲解

    注解:

    在实际的开发过程中我们会经常使用到注解,如果在开发过程中你不懂注解,那么说明你不是一名合格的程序员。所以我们有必要对注解进行深入的了解。

    Annotation可以像修饰符一样被使用,可用于修饰包,类,构造器,方法,成员变量,参数,局部变量的声明,这些信息被保存在Annotaion的“name=value”对中。

    jdk内置了三个基本的注解:@Override @Deprecated @SuppressWarnings

    我们在学习JAVA基础的时候,经常使用到的注解有:

    @Override 告诉编译器这个方法是覆盖父类的方法

    @WebServlet("/test") 表示某个类是一个Servlet,Web容器就会识别这个注解,在运行的时候调用它。

    @Controller("/test") 表示某个类是一个控制器,告诉spring框架该类是一个控制器。

    注解和注释是完全不同的两个东西,看起来有点类似,其实完全不同,注解会影响程序的运行。注释是给开发人员看的,不会影响程序的编译和运行。注解并不是给开发人员看的,是用于给程序看的,会影响程序的编译和运行,比如给编译器、tomcat、框架看的。

    1.1注解的作用范围

    自定义开发一个web容器,基本功能是加载servlet,需要管理它的生命周期,所以必须先识别程序中的哪些类是Servlet。程序启动的时候,扫描所有的类,找出添加了@WebServlet注解的类,进行加载(类似于spring IOC容器的启动过程)。

    @WebServlet 是在程序运行的时候起作用的,那么JAVA就把他的作用范围规定为RUNTIME.

    @Override 是给编译器看到饿,编译器工作的时候识别出包含了@Override 注解的方法,就去检查他上层父类的相应方法,存在则通过,否则报错。

    @Override是编译的时候起作用,JAVA就把他的作用范围规定为SOURCE.

    @Test 是生成测试代码,一般在框架中使用的比较多,作用范围是SOURCE.

    JDK5.0提供了4个标准的meta-annotaion类型的元注解,分别是:target retention documented inherited

    1.2@Target 指定注解针对的地方

    ElementType:

    ElementType.TYPE : 针对类 、接口

    ElementType.FIELD : 针对成员变量

    ElementType.METHOD: 针对成员方法

    ElementType.PARAMETER : 针对方法参数

    ElementType.CONSTRUCTOR: 针对构造器

    ElementType.PACKAGE:针对包

    ElementType.ANNOTATION: 针对注解

    1.3 @Retention 指定注解的保留域

    也可以理解为注解的存活时间

    RetentionPolicy:

    RetentionPolicy.SOURCE 源代码级别,由编译器处理,处理之后就不再保留

    RetentionPolicy.CLASS 注解信息保留到类对应的class 文件中,这是一个默认行为,也就是说,如果不进行指定的时候,默认就是他。

    RetentionPolicy.RUNTIME 由JVM读取,运行的时候使用,也就是说,只有声明为runtime声明周期的注解,才能通过反射进行获取。

    1.4@Documented:(在实际的使用中比较少)

    用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档,默认情况下,javadoc是不包括注解的。

    定义为Documented的注解必须设置Retention 值为 RUNTIME.

    1.5@Inherited:(在实际的使用中比较少)

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

    比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类级别的注解。

    ​ 实际应用中,使用较少

    1.6自定义注解

    package com.annotationpractice;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    //添加源注解,用来指明当前的注解是干什么用的
    @Target(ElementType.METHOD)//表示这个注解只能添加到方法上面
    @Retention(RetentionPolicy.RUNTIME)//表示该注解只能在运行的时候进行调用
    public @interface InitMethod {
    }
    
    
    package com.annotationpractice;
    
    public class InitDemo {
        @InitMethod
        public void init(){
            System.out.println("init......");
        }
    
        public void test(){
    
        }
    }
    
    package com.annotationpractice;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * 测试注解的使用
     */
    public class Test {
        public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class<?> clazz = Class.forName("com.annotationpractice.InitDemo");
            Method[] methods = clazz.getMethods();
            if(null != methods){
                for (Method method : methods) {
                    boolean flagInitMethod = method.isAnnotationPresent(InitMethod.class);//看看该方法中有没有该注解
                    if(flagInitMethod){
                        method.invoke(clazz.getConstructor(null).newInstance(null),null);
                    }
                }
            }
        }
    }
    运行结果:init......
    

    注意:自定义注解必须配上信息处理流程才有意义。也就是说必须要使用反射的方式。

    1.7 jdk8中注解的新特性 可重复注解 类型注解

    可重复注解

    ①在MyAnnotation上声明@Repetable,成员值为MyAnnotations.class

    ②MyAnnotation的Target和Retention等元注解与MyAnnotations相同

    jdk8之前写该注解:

    ////这是在jdk8之前的写法
    //@MyAnnotations({@MyAnnotation(value = "hi"),@MyAnnotation(value = "abc")})
    

    jdk8写该注解:

    @MyAnnotation(value = "abc")
    @MyAnnotation(value = "hi")
    
    package com.annotationpractice;
    
    import com.sun.deploy.security.ValidationState;
    
    import java.lang.annotation.*;
    import java.lang.reflect.Type;
    
    import static java.lang.annotation.ElementType.*;
    
    /**
     * 自定义注解
     */
    @Repeatable(MyAnnotations.class)
    @Target({TYPE,FIELD,METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        String[] value() default "hello";
    }
    
    
    package com.annotationpractice;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.ElementType.*;
    
    /**
     * 自定义注解
     */
    @Target({TYPE,FIELD,METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotations {
        MyAnnotation[] value();
    }
    
    
    package com.annotationpractice;
    
    /**
     * 如何自定义注解 参照@suppresswarning定义
     * 1.注解声明为 @interface
     * 2.内部定义成员,通常使用value表示
     * 3.可以指定成员的默认值,使用default定义
     * 4.如果自定义注解没有成员,表明是一个标识作用
     *
     */
    //@MyAnnotation(value = "hi")  //当然这里可以不指定,也是可以的
    ////这是在jdk8之前的写法
    //@MyAnnotations({@MyAnnotation(value = "hi"),@MyAnnotation(value = "abc")})
    @MyAnnotation(value = "abc")
    @MyAnnotation(value = "hi")
    public class Person {
        private String name;
        private int age;
    
    //    @MyAnnotation  //因为在注解内部已经指定了值了,所以,这里如果没有特别的需要,也是可以不写值的。
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public Person() {
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    

    类型注解

    ElementType.TYPE_PARAMETER: 表示该注解能写在类型变量的声明语句中(如:泛型声明)

    ElementType.TYPE_USE: 表示该注解能写在使用类型的任何语句中

    package com.annotationpractice;
    
    import com.sun.deploy.security.ValidationState;
    
    import java.lang.annotation.*;
    import java.lang.reflect.Type;
    
    import static java.lang.annotation.ElementType.*;
    
    /**
     * 自定义注解
     */
    @Repeatable(MyAnnotations.class)
    @Target({TYPE,FIELD,METHOD,TYPE_PARAMETER,TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        String[] value() default "hello";
    }
    
    
    package com.annotationpractice;
    
    import java.lang.reflect.Array;
    import java.util.ArrayList;
    
    /**
     * 类型注解
     */
    public class Generic<@MyAnnotation T> {
        public void show() throws @MyAnnotation RuntimeException{
            ArrayList<@MyAnnotation String> list = new ArrayList<>();
            int num=(@MyAnnotation int) 10L;
        }
    }
    
    

    案例:简单的测试框架

    参考网址:https://blog.csdn.net/zzu_seu/article/details/104673681

  • 相关阅读:
    Spring_AOP动态代理详解(转)
    Java中spring读取配置文件的几种方法
    SpringMVC工作原理2(代码详解)
    SpringMVC工作原理1(基础机制)
    Web服务器和应用服务器简介
    WEB服务器与应用服务器解疑
    WebService基本概念及原理
    HTTP协议
    TCP、UDP协议间的区别(转)
    HTTP、TCP、UDP以及SOCKET之间的区别/联系
  • 原文地址:https://www.cnblogs.com/dongyaotou/p/15732559.html
Copyright © 2011-2022 走看看