zoukankan      html  css  js  c++  java
  • Java源码赏析(四)Java常见注解

    元注解

    @Target :标识注解的目标,默认为所有

    • ElementType.TYPE(用于类)
    • ElementType.FIELD(用于域,包括enum)
    • ElementType.METHOD(用于方法)
    • ElementType.PARAMETER(用于正式参数)
    • ElementType.CONSTRUCTOR(类型构造方法)
    • ElementType.LOCAL_VARIABLE(用于本地变量)
    • ElementType.ANNOTATION_TYPE(用于注解)
    • ElementType.PACKAGE(用于包)
    • ElementType.TYPE_PARAMETER(java8,用于输入参数)
    • ElementType.TYPE_USE (java8,用于类型)

    @Retention:注解保留到哪

    • RetentionPolicy.SOURCE (只保留到源码,编译为.class文件时忽略)
    • RetentionPolicy.CLASS (只保留到.class文件,运行时忽略,default默认)
    • RetentionPolicy.RUNTIME (运行时保留,可以通过反射机制读取注解的信息。)

    @Documented:将此注解保存在 Javadoc 中

    @Inherited:允许子类继承父类的注解

    @Repeatable:用于重复使用注解(Java8新增)

    常用注解

    一、@Override

     常用于重写父类的方法,或实现接口的方法,若不满足则报错。

    package java.lang;
    
    import java.lang.annotation.*;
    
    /**
     * 使用在方法上,只存在在源码上
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Override {
    }

    二、@Deprecated

     常用于标注一个方法被弃用。

    package java.lang;
    
    import java.lang.annotation.*;
    import static java.lang.annotation.ElementType.*;
    
    /**
     * 记录JavaDoc,保留至运行时,可使用在构造方法,属性(包括枚举),本地变量,方法,包,公共参数和类
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }

    三、@SuppressWarnings

    常用于忽略特定警告,@SuppressWarnings("unchecked", "deprecation")可以同时忽略多个警告。

    package java.lang;
    
    import java.lang.annotation.*;
    import static java.lang.annotation.ElementType.*;
    
    /**
     * 在类型、域、方法、正是参数、构造方法、本地变量上使用,只存在于源码
     */
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        /**
         * 一般取 unchecked/deprecation,表示忽略 unchecked/deprecation 警告信息
         */
        String[] value();
    }

     四、@SafeVarargs (Java7)

    常用于抑制varargs相关的未检查警告,一般只能用于static、final方法

    package java.lang;
    
    import java.lang.annotation.*;
    
    /**
     * 能记录JavaDoc,保留至运行时,使用在构造方法和方法上
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
    public @interface SafeVarargs {}

    五、@FunctionalInterface (Java8)

     编译器检测接口是否符合函数式接口定义

    package java.lang;
    
    import java.lang.annotation.*;
    
    /**
     * 能记录JavaDoc,存在于运行时,只能使用在类上
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FunctionalInterface {}

    自定义注解

    首先定义一个注解

    package com.example.demo.util.annotation;
    
    import java.lang.annotation.*;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    @Documented
    @Inherited
    public @interface MyAnnotation {
        String value() default "001";
    }

    可以看到,在Student的sNo属性上使用了该注解

    package com.example.demo.util.annotation;
    
    import lombok.Data;
    import lombok.AllArgsConstructor;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student {
        @MyAnnotation
        private String sNo;
    
        private String sName;
    }

    处理注解

    package com.example.demo.util.annotation;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Objects;
    
    public class AnnotationTest {
    
        public static void main(String[] args) {
            //创建一个学号为 002 的学生 kw
            Student student = new Student("002", "kw");
    
            //获取学生对象对应的类
            Class<? extends Student> clazz = student.getClass();
            //获取学生类的属性
            Field[] declaredFields = clazz.getDeclaredFields();
            /** 循环判断是否存在注解@MyAnnotation
             * 若存在则获取该属性的set方法
             * 并使用该方法将值改为@MyAnnotation的value值
             */
    @MyAnnotation的value
            for (Field field: declaredFields) {
                if (field.isAnnotationPresent(MyAnnotation.class)) {
                    MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
                    if (Objects.nonNull(annotation)) {
                        String name = field.getName();
                        try {
                            Method setMethod = clazz.getDeclaredMethod(
    "set" + name.substring(0, 1).toUpperCase() + name.substring(1), String.class);
                            String annotationValue = annotation.value();
                            setMethod.invoke(student, annotationValue);
                        } catch (NoSuchMethodException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
    
                }
            }
            //打印
            System.out.println(student);
        }
    }
    
    /** 输出
    Student(sNo=001, sName=kw)
    */
  • 相关阅读:
    STL中string的源码解读
    Sublime插件:Terminal
    sublime text3安装Package Control
    [转]Sublime Text操作
    python itertools模块实现排列组合
    pandas 选择某几列
    更改pandas dataframe 列的顺序
    pandas之groupby分组与pivot_table透视表
    IPython notebook快捷键(Jupyter notebook)
    人生的意义
  • 原文地址:https://www.cnblogs.com/kwanwoo/p/13668927.html
Copyright © 2011-2022 走看看