Here’s a question I’d like to discuss with the big guys. How to use the five attributes in ElementType? Don’t leave a message explaining the literal meaning.

Define an annotation

package com.datang.pet.data.anno;
public @interface NotNull {
}
Copy the code

View Code

The above code defines an @notnull annotation. This annotation can be used anywhere.

package com.datang.pet.data.anno; @NotNull public class TestBean { @NotNull public String name; @NotNull public TestBean(){} @NotNull public void show(@NotNull int age){ @NotNull int s = 12; }}Copy the code

View Code

The code above uses the @notnull annotation. As you can see, you can use custom annotations almost anywhere in a class.

Limit the scope @target

Custom annotations can be decorated with meta-annotations, which are annotations that come with JDK packages and are usually used to describe permissions for custom annotations.

This is the @target meta-annotation. We can add this annotation to @notnull’s custom annotation.@Target the value of the annotation’s value attribute is an array type, and the elements of the array must be enumerations of ElementType

/* * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *  * * * * * * * * * * * * * * * * * * * */ package java.lang.annotation; /** * Indicates the contexts in which an annotation type is applicable. The * declaration contexts and type contexts in Which an annotation type may be * applicable are specified in JLS 9.6.4.1, and denoted in source code by enum * constants of {@link ElementType java.lang.annotation.ElementType}. * * <p>If an {@code @Target} meta-annotation is not present on an annotation type * {@code T} , then an annotation of type {@code T} may be written as a * modifier for any declaration except a type parameter declaration. * * <p>If an {@code @Target} meta-annotation is present, the compiler will enforce * the usage restrictions indicated by {@code ElementType} * enum constants, In line with JLS 9.7.4. * * <p> this {@code @Target} meta-annotation indicates that the * declared type is itself a meta-annotation type. It can only be  used on * annotation type declarations: * <pre> * &#064; Target(ElementType.ANNOTATION_TYPE) * public &#064; interface MetaAnnotationType { * ... * } * </pre> * * <p>This {@code @Target} meta-annotation indicates that the declared type is * intended solely for use as a member type in complex annotation type * declarations. It cannot be used to annotate anything directly: * <pre> * &#064; Target({}) * public &#064; interface MemberType { * ... * } * </pre> * * <p>It is a compile-time error for a single {@code ElementType} constant to * appear more than once in an {@code @Target} annotation. For example, the * following {@code @Target} meta-annotation is illegal: * <pre> * &#064; Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD}) * public &#064; interface Bogus { * ... *} * </pre> * * @since 1.5 * @jls 9.6.4.1 @Target * @Jls 9.7.4 Where Annotations May Appear */ @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(); }Copy the code

View Code

/* * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *  * * * * * * * * * * * * * * * * * * * */ package java.lang.annotation; /** * The constants of this enumerated type provide a simple classification of the * syntactic locations where annotations may appear in a Java program. These * constants are used in {@link Target java.lang.annotation.Target} * meta-annotations to specify where it is legal to write annotations of a * given type. * * <p>The syntactic locations where annotations may appear are split into * <em>declaration contexts</em> , where annotations apply to declarations, and * <em>type contexts</em> , where annotations apply to types used in * declarations and expressions. * * <p>The constants {@link #ANNOTATION_TYPE} ,  {@link #CONSTRUCTOR} , {@link * #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} , * {@link #PARAMETER} , {@link #TYPE} , And {@link #TYPE_PARAMETER} respond * to the declaration contexts in JLS 9.6.4.1. * * <p>For example, an annotation whose type is meta-annotated with * {@code @Target(ElementType.FIELD)} may only be written as a modifier Buta collection of artifacts to The 15 Type Contexts in JLS * 4.11, as well as to two declaration contexts: type declarations (including * annotation type declarations) and type parameter declarations. * * <p>For example, an annotation whose type is meta-annotated with * {@code @Target(ElementType.TYPE_USE)} may be written on the type of a field * (or within the type of the field, if it is a nested, parameterized, or array * type), and may also appear as a modifier for, say, a class declaration. * * <p>The {@code TYPE_USE} constant includes type declarations and type * parameter declarations as a convenience for designers of type checkers which * give semantics to annotation types. For example, if the annotation type * {@code NonNull} is meta-annotated with * {@code @Target(ElementType.TYPE_USE)}, then {@code @NonNull} * {@code class C {... }} could be treated by a type checker as indicating that * all variables of class {@code C} are non-null, while still allowing * variables of other classes to be non-null or not non-null based on whether * {@code @NonNull} * * @author Joshua Bloch * @since 1.5 * @jls 9.6.4.1 @Target * @jls 4.1 the Kinds  of Types and Values */ 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}Copy the code

View Code

Let’s try using a few attributes for the @notnull annotation.

package com.datang.pet.data.anno;

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

@Target(value = {ElementType.TYPE})
public @interface NotNull {
}
Copy the code

View Code

When we assigned the value of the @target meta-annotation to elementType. TYPE, we found that the TestBean class using the @notnull annotation went viral. Shows that @notnull cannot be used in member variables, constructors, etc. The reason is that when a custom annotation does not use the @target attribute, it does not limit the scope of the annotation, but when it does use the @target meta-annotation, it only uses the value of the @target annotation.

Let’s add a few more scopes to the @notnull annotation.

package com.datang.pet.data.anno;

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

@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, 
        ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
public @interface NotNull {
}
Copy the code

View Code

The @target meta-annotation declares six available scopes: classes, methods, member variables, constructors, method parameters, and local variables. These six are also the longest used. In fact, the JDK has supported 10 applications up to 1.8.

Attributes of annotations

The meta annotation @target has a value attribute, and our custom annotations can also have a value attribute.

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

@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
        ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
public @interface NotNull {
    
    String value();
}
Copy the code

View Code

We declare a value attribute for the custom annotation @notnull. Classes with @notnull annotations are failing because we declared the value attribute but did not give it a value.

@NotNull(value = "a") public class TestBean { @NotNull(value = "a") public String name; @NotNull(value = "a") public TestBean() { } @NotNull("a") public void show(@NotNull("a") int age) { @NotNull("a") int s = 12; }}Copy the code

View Code

Add an attribute to the annotation. If the attribute of the annotation is value and only that attribute, the attribute name can be ignored.

If you have more than one attribute, you cannot omit the value attribute name.

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

@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
        ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
public @interface NotNull {

    String value();
    
    String name();
}
Copy the code

View Code

 

We can assign a default value to the attribute when we create the annotation so that the attribute is not required to be overridden when the annotation is used.

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

@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
        ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
public @interface NotNull {

    String value();

    String name();

    int age() default 100;
}
Copy the code

View Code

Read the note

When we use annotations in code, they have no real meaning. The point of annotations is that this is how we deal with classes, methods that have these annotations.

So why don’t we get annotations at this point? The reason is that our custom annotations also need to have @Retention annotations. The annotation has a value attribute of type RetentionPolicy

There are three optional values for this type.

/* * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *  * * * * * * * * * * * * * * * * * * * */ package java.lang.annotation; /** * Annotation retention policy. The constants of this enumerated type * describe the various policies for retaining annotations. They are used * in conjunction with the {@link Retention} meta-annotation type to specify * how long Annotations are to be retained. ** @author Joshua Bloch * @since 1.5 */ 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 }Copy the code

View Code

The SOURCE comment is discarded by the compiler. CLASS is stored in the CLASS file and is the default value, which can be read using a specific CLASS text reader. Normally, we use the third value. Runtimes are reserved by the VM at RUNTIME, so they can be read reflexively.

package com.datang.pet.data.anno;

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

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

    String value();

    String name();

    int age() default 100;
}
Copy the code

View Code

Reads the attribute value of the annotation

package com.datang.pet.data.anno; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Parameter; public class Main { public static void main(String[] args) throws Exception { TestBean testBean = new TestBean(); Class<? extends TestBean> aClass = testBean.getClass(); NotNull annotation = aClass.getAnnotation(NotNull.class); if (annotation ! = null) {system.out.println ("TestBean class with @notnull annotation "); String value = annotation.value(); String name = annotation.name(); int age = annotation.age(); System.out.println(value + "--" + name + "--" + age); } else {system.out.println ("TestBean class has no @notnull annotation "); } Field nameField = aClass.getField("name"); NotNull annotation1 = nameField.getAnnotation(NotNull.class); if (annotation1 ! = null) {system.out.println ("name with @notnull annotation "); String value = annotation1.value(); String name = annotation1.name(); int age = annotation1.age(); System.out.println(value + "--" + name + "--" + age); } else {system.out.println (" no @notnull annotation on name "); } Constructor<? extends TestBean> declaredConstructor = aClass.getDeclaredConstructor(); NotNull annotation2 = declaredConstructor.getAnnotation(NotNull.class); if (annotation2 ! = null) {system.out.println (" @notnull on constructor "); String value = annotation2.value(); String name = annotation2.name(); int age = annotation2.age(); System.out.println(value + "--" + name + "--" + age); } else {system.out.println (" No @notnull annotation on constructor "); } Method showMethod = aClass.getMethod("show",int.class); NotNull annotation3 = showMethod.getAnnotation(NotNull.class); if (annotation3 ! = null) {system.out.println ("show method with @notnull annotation "); String value = annotation3.value(); String name = annotation3.name(); int age = annotation3.age(); System.out.println(value + "--" + name + "--" + age); } else {system.out.println ("show method has no @notnull annotation "); } Parameter[] parameters = showMethod.getParameters(); for (Parameter parameter:parameters){ String name1 = parameter.getName(); if (parameter.getName().equals("age")){ NotNull annotation4 = parameter.getAnnotation(NotNull.class); System.out.println("age argument annotated with @notnull "); String value = annotation4.value(); String name = annotation4.name(); int age = annotation4.age(); System.out.println(value + "--" + name + "--" + age); }}}}Copy the code

View Code

Can subclasses inherit annotations from their parent class?

package com.datang.pet.data.anno;

public class TestBean2 extends TestBean{

}
Copy the code

View Code

As a result, subclasses do not inherit annotations from their parent class.

When a custom annotation is annotated, it indicates that the annotation can be Inherited. A parent class must be a class, not abstract, and not an interface.

package com.datang.pet.data.anno;

import java.lang.annotation.*;

@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
        ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface NotNull {

    String value();

    String name();

    int age() default 100;
}
Copy the code

View Code