Java Annotation Type (@Annotation)
Java annotations are a new feature introduced in JDK5. Given that most of the current frameworks (such as Spring) use annotations to simplify the code and improve coding efficiency, it is necessary for a Java engineer to master and understand annotations. .
1. Understand Java annotations
In fact, pubic, static void
there is not much difference between the use of Java annotations and ordinary modifiers ( etc.). The following examples are common annotations:
/**
* @author zn
* @date 2020/3/30
**/
public interface Animal {
void eat();
}
/**
* @author zn
* @date 2020/3/30
**/
public class Dog implements Animal {
@Deprecated
@Override
public void eat() {
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
Of course, we have already seen the @Test
annotation. This annotation does not indicate that it is a unit test and can be executed directly.
In this example, @Deprecated means that this method is outdated. The next version may be abolished. @Override means that this method is inherited or implemented. If the method name is written incorrectly, an error will be reported.
Annotations can be reclassed or inside
For @Deprecated
sum @SuppressWarnings("uncheck")
, it is a built-in annotation in Java itself, which can often be seen in the code, but this is not a good thing. After all, when a method or class has an @Deprected
annotation, it means that the method or class has expired and is not It is recommended to use, @SuppressWarnings
which means to ignore the specified warning. For example @SuppressWarnings("uncheck")
, this is the simplest way to use annotations. Let's take a look at the basic syntax of annotation definitions.
2. Basic Grammar
(1) Statement annotations and meta annotations
Let's take a look at how the previous Test
annotations are declared:
//声明Test注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test{
}
We use a @interface
declared Test
annotation, and use the @Target
annotation to pass in the ElementType.METHOD
parameter to indicate that it @Test
can only be used on the method, which @Retention(RetentionPolicy.RUNTIME)
is used to indicate that the life of the annotation is runtime. From the code point of view, the definition of the annotation is very similar to the definition of the interface. , After all, Test.class
files will be generated after compilation . For @Target
sum @Retention
is a meta-annotation provided by Java, the so-called meta-annotation is an annotation that marks other annotations, which are introduced below:
@Target
Used to constrain the places where annotations can be applied (such as methods, classes, or fields), whichElementType
is an enumeration type, which is defined as follows, and also represents the possible range of values
public enum ElementType{
//标明该注解可以用于类、接口(包括注解类型)或enum声明
TYPE,
//标明该注解可以用于字段(域)声明,包括enum实例
FIELD,
//标明该注解可以用于方法声明
METHOD,
//标明该注解可以用于参数声明
PARAMETER,
//标明注解可以用于构造函数声明
CONSTRUCTOR,
//标明注解可以用于局部变量声明
LOCAL_VARIABLE,
//标明注解可用于注解声明(应用于另一个注解上)
ANNOTATION_TYPE,
//标明注解可以用于包声明
PACKAGE,
/**
*标明注解可以用于类型参数声明(1.8新加入)
*@since 1.8
*/
TYPE_PARAMETER,
/**
*类型使用声明(1.8新加入)
*@since1.8
*/
TYPE_USE
}
Note that when the annotation does not specify a Target
value, the annotation can be used on any element, and multiple values are {}
included and separated by commas, as follows:
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
@Retention
Used to constrain the life cycle of annotations, there are three values respectively, source code level
source
, Class file level
class
Or runtime level
runtime
, And its meaning is as follows:
SOURCE
: Annotation will be discarded by the compiler (this type of annotation information will only be retained in the source code. After the source code is compiled, the annotation information will be discarded and will not be retained in the compiled.class
file)CLASS
: Annotation.class
is available in the file, but it will be discarded by the JVM (this type of annotation information will be kept in the source code and in the.class
file, and will not be loaded into the virtual machine during execution). Please note that when the annotation has noRetention
value defined , The default value isCLASS
, such as Java built-in annotations,@Override,@Deprecated,@SuppressWarning
etc.RUNTIME
: The annotation information will be retained during the runtime (JVM), so the annotation information can be read through the reflection mechanism (the source code, the.class
file, and the execution time have annotation information), such asSpringMVC
in@Controller, @Autowired, @RequestMapping
.
(2) Annotation elements and their data types
Through the above @Test
definition of annotations, we understand the process of annotation definition. Since @Test
there are no other elements defined internally, it @Test
is also called marker annotation , but in custom annotations, some elements are generally included to represent certain values , To facilitate the use of the processor, this will be seen in the following example:
@Target(ElementType.TYPE)//只能应用于类上
@Retention(RetentionRolicy.RUNTIME)//保存到运行时
public @interface DBTable{
String name() default "";
}
The above defines an DBTable
annotation named , which is mainly used for the mapping of the database table domain Bean class (a complete case analysis will be available later). Unlike the previous Test
annotations, we declare a String
type of name
element, and its default value is a null character String, but it must be noted that the declaration corresponding to any element should adopt the method declaration method, and at the same time, you can choose to default
provide default values. The @DBTable
usage is as follows:
@DBTable(name = "MEMBER")
public class Member{
//...
}
The element data types supported by annotations are listed above String
, and the following data types are also supported:
- All basic types (
int, float, boolean, byte, double, char, long, short
) String
Class
enum
Annotation
- Array of the above type
If other data types are used, the compiler will throw a compilation error. Note that you can use basic types when declaring annotated elements, but you are not allowed to use any packaging types. At the same time, it should be noted that annotations can also be used as element types. It is nested annotations. The following code demonstrates the use of the above types:
package com.guirunxiang.annotationdemo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Reference{
boolean next() default false;
}
public @interface AnnotationElementDemo {
//枚举类型
enum Status {FIXED, NORMAL};
//声明枚举
Status status() default Status.FIXED;
//布尔类型
boolean showSupport() default false;
//String类型
String name() default "";
//class类型
Class<?> testCase() default Void.class;
//注解嵌套
Reference reference() default @Reference(next = true);
//数组类型
long[] value();
}
(3) Compiler restrictions on default values
The compiler is a bit picky about the default value of the element. First, the element cannot have an indeterminate value. In other words, the element must either have a default value or provide the value of the element when using the annotation. Second, for non-basic types of elements, either in the statement or in the source code annotation interface to define default values are not to null
the value.
(4) Annotation does not support inheritance
Annotations do not support inheritance, so you cannot use keywords extends
to inherit one @interface
, but after the annotation is compiled, the compiler will automatically inherit the java.lang.annotation.Annotation
interface. Here we decompile the DBTable
annotation defined earlier :
package com.guirunxiang.annotationdemo;
import java.lang.annotation.Annotation;
//反编译后的代码
public interface DBTable extends Annotation{
public abstract String name();
}
Although it is found after decompilation that the DBTable
annotation inherits the Annotation
interface, extends
keyword inheritance is still not available when defining annotations @interface
.
(5) Shortcut
The so-called shortcut is that the named value
element is defined in the annotation, and when using the annotation, if the element is the only element that needs to be copied, then there is no need to use the key = value
syntax at this time , and only the value
required elements of the element are given in parentheses Value. This can be applied to any legal type of element, but this restricts the element name must be value
. A simple case is as follows:
package com.guirunxiang.annotationdemo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//定义注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface IntegerValue{
int value() default 0;
String name() default "";
}
//使用注解
public class QuicklyWay {
//当只想给value赋值时,可以使用一下快捷方式
@IntegerValue(20)
public int age;
//当name也需要赋值是必须采用key = value的方式赋值
@IntegerValue(value = 1000, name = "MONEY")
public int money;
}
3. Java built-in annotations
Then look at the built-in annotations provided by Java, there are mainly three, as follows:
@Override
: Used to indicate the coverage of this method Fred method, the source code is as follows:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override{
}
Deprecated
: Used to mark obsolete methods or classes, the source code is as follows, about@Documented
later analysis:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated{
}
@SuppressWarnnings
: Used to selectively turn off the compiler's warnings for classes, methods, member variables, and variable initialization. The source code is as follows:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
There is an String
array inside , the main receiving values are as follows:
parameter name | Description |
---|---|
"deprecation" |
Warning when using deprecated classes or methods |
"unchecked" |
A warning when an unchecked conversion is performed, for example, when a collection is used, Generics is not used to specify the type saved by the collection |
"fallthrough" |
When switch one kind of the block direct access to the case without break warning of |
"path" |
Warning when there is a path that does not exist in the class path, source file path, etc. |
"serial" |
When the missing of sequence in the class may be serialVersionUID defined when the warning |
"finally" |
Any finally warning clause can not be completed properly |
"all" |
Warning about all the above |
These three annotations are relatively simple, let's look at a simple case:
//注明该类已过时,不建议使用
@Deprecated
Class A{
public void A(){ }
//注明该方法已过时,不建议使用
@Deprecated
public void B(){ }
}
class B extends A{
@Override //标明覆盖父类A的A方法
public void A(){
super.A();
}
//去掉检测警告
@SuppressWarnings({"uncheck", "deprecation"})
public void C(){ }
//去掉检测警告
@SuppressWarnings("uncheck")
public void D(){ }
}
Earlier we analyzed two kinds of meta-annotations, @Target
and @Retention
. In addition to these two kinds of meta-annotations, Java also provides two other kinds of meta-annotations, @Documented
and @Inherited
, which are introduced below:
@Documented
Modified comments will be generatedjavadoc
in
//使用@Documented
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentA {
}
//没有使用@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentB {
}
//使用注解
@DocumentA
@DocumentB
public class DocumentDemo {
public void A(){
}
}
Use the javadoc
command to generate documentation:
javadoc DocumentDemo.java DocumentA.java DocumentB.java
As follows, you can find that the @Documented
annotations defined using meta annotations @DocumentA
will be generated in the javadoc, but @DocumentB
not in the doc document. This is @Documented
the role of meta annotations .
img
image-20200323120949046.png
@Inherited
Annotations can be inherited, but this is not true inheritance, just by using@Inherited
, you can let subclassClass
objects use togetAnnotations()
get@Inherited
the annotations modified by the parent class , as follows:
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentA {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DocumentB {
}
@DocumentA
class A{ }
class B extends A{ }
@DocumentB
class C{ }
class D extends C{ }
//测试
public class DocumentDemo {
public static void main(String... args){
A instanceA=new B();
System.out.println("已使用的@Inherited注解:"+Arrays.toString(instanceA.getClass().getAnnotations()));
C instanceC = new D();
System.out.println("没有使用的@Inherited注解:"+Arrays.toString(instanceC.getClass().getAnnotations()));
}
/**
* 运行结果:
已使用的@Inherited注解:[@com.zejian.annotationdemo.DocumentA()]
没有使用的@Inherited注解:[]
*/
}
Link: https://www.jianshu.com/p/2f96679ff094
●The strongest Tomcat8 performance optimization in history
● Why can Alibaba resist 10 billion in 90 seconds? --The evolution of server-side high-concurrency distributed architecture
● B2B e-commerce platform--ChinaPay UnionPay electronic payment function
● Learn Zookeeper distributed lock, let interviewers look at you with admiration
● SpringCloud e-commerce spike microservice-Redisson distributed lock solution
Check out more good articles, enter the official account--please me--excellent in the past
A deep and soulful public account 0.0