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

Java注解基础学习笔记

程序员文章站 2024-02-16 09:43:46
...

Java注解基础学习笔记

1.注解基本概念

  注解是一种引用数据类型,它编译后的文件是.class文件。注解的基本用法是@注解类型名(参数赋值),注解的作用范围可以是类,域,方法,构造函数,局部变量等,不过特定的注解的作用范围需要看该注解的具体规定。

  了解注解基础对后期注解开发有很大的帮助。



2.JDK1.8常见的注解

aaa@qq.com

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

  该注解只能放在方法上,用于编译阶段判定该方法是不是对父类或是接口重写的方法,这样可以避免程序员打错字或是对不存在的方法进行重写。



aaa@qq.com

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

  该注解主要表示构造函数,域,方法等是否已经过期。过期不代表不能使用。如果使用,则会在代码中出现删除线,编译时会有警告。

Java注解基础学习笔记

Java注解基础学习笔记



2.3元注解

  元注解就是注解的注解,常见的有@Target和@Retention。前者表示注解的范围,后者表示注解保存的地方。

@Target

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

该元注解里面有一个value属性,它表示被@Target修饰的注解的作用范围,比如类上或是构造函数上等

ElementType的类型如下所示

ElementType

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

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

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

@Retention

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

该元注解有一个value属性,该值表示被@Retention修饰的注解最终存在的位置。

RetentionPolicy类型如下:

RetentionPolicy

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

其中

  1. SOURCE表示被@Retention修饰的注解只能保存在源代码中,并不能存储到class文件中,比如@Override。
  2. CLASS表示被@Retention修饰的注解能存储到class文件中。
  3. RUNTIME表示表示被@Retention修饰的注解能存储到class文件中,而且还能在运行时被反射。


3.自定义注解

3.1基本格式

[可见性修饰符] @interface 自定义注解名{
    
    属性1;
    属性2;
    属性3;
}



3.2关于属性

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

    String value();
    //设置默认值  
//    String name() default “Lord_Bao";
}

@MyAnnotation("lord_bao")
class TestMyAnnotation{


    public static void main(String[] args) {

    }
}
  1. 属性的类型范围
    • 8大基本类型:byte short int long float double boolean char
    • Class String
    • 枚举类型
    • 上述类型的数组形式
  2. 在外部用注解的时候,必须要对相应的属性进行设值。不过可以在注解类里面自己设置默认值。
  3. 特殊情况:当注解类里面只有一个value属性的时候,在外部使用注解的时候可以不用显式写value。
  4. 特殊情况:当属性是数组的形式且该数组只有一个元素的时候,可以不用写{}



4.反射+注解创建对象

场景描述

通过反射,创建自定义类的对象实例。
要求 该类必须被 @MyBean修饰
其次 该类必须要有一个id域,且该id域要被@MyValue注解修饰 并赋值

MyBean

package com.lordbao.DIYAnnotation;

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

/**
 * @Author Lord_Bao
 * @Date 2020/9/14 14:32
 * @Version 1.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyBean {
}

MyValue

package com.lordbao.DIYAnnotation;

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

/**
 * @Author Lord_Bao
 * @Date 2020/9/14 14:33
 * @Version 1.0
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {

    int value();
}

自定义的Student类

@MyBean
class Student{

    @MyValue(1)
    private  int id;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                '}';
    }
}

测试代码

package com.lordbao.DIYAnnotation;

import java.lang.reflect.Field;

/**
 * @Author Lord_Bao
 * @Date 2020/9/14 14:35
 * @Version 1.0
 *
 * 场景模拟:
 *
 * 通过反射,创建自定义类的对象实例。
 * 要求 该类必须被 @MyBean修饰
 * 其次 该类必须要有一个id域,且该id域要被@MyValue注解修饰 并赋值
 *
 *
 */
public class TestDIYAnnotation {

    public static void main(String[] args) throws Exception {
        Class studentClass = Class.forName("com.lordbao.DIYAnnotation.Student");

        //判断studentClass 是不是被自定义的注解修饰
        if (studentClass.isAnnotationPresent(MyBean.class)){
            Student student = (Student) studentClass.newInstance();

            Field idField = studentClass.getDeclaredField("id");
            idField.setAccessible(true);
            //判断idField是否被自定义的注解修饰
            if (idField.isAnnotationPresent(MyValue.class)){
                //value()方法  与  MyValue类的value对应
                int id = idField.getAnnotation(MyValue.class).value();
                idField.set(student,id);

                System.out.println(student);
            }else {
                throw  new  Exception("该类的id没有被@MyValue注解修饰,无法实例化该对象");
            }
        }else {
            throw  new  Exception("该类没有被@MyBean注解修饰,无法实例化该对象");
        }

    }
}

结果

Student{id=1}