Comb technology stack knowledge point afresh
What are annotations?
Annotation is a special kind of interface, the annotation inherited from Java. Lang. The annotation. The annotation.
/** The common interface extended by all annotation types. Note that an interface that manually extends this one does not define an annotation type. Also note that this interface does not itself define an annotation type. More information About annotation types can be found in section 9.6 of The Java™ Language Specification. The reflation.annotatedElement interface discusses compatibility concerns when evolving an annotation type from being non-repeatable to being repeatable. */
public interface Annotation {... }Copy the code
The Annotation interface documentation description:
- All Annotation types inherit the Annotation interface
- Manual display inherits the Annotation interface and is not defined as an Annotation type
- The Annotation itself is not defined as an Annotation type
Write a note
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Demo {
}
Copy the code
Java to view the bytecode: javap.demo.class:
Compiled from "Demo.java"
public interface org.byron4j.cookbook.javacore.anno.Demo extends java.lang.annotation.Annotation {
Copy the code
Through bytecode, we can see that annotations inherit from the Annotation interface.
The usefulness of annotations
If we want to learn something, we have to know what it does. There is no Java programmer who doesn’t know the Spring framework. The Spring framework defines a large number of annotations, based on which we can develop commercial projects with almost zero configuration. SpringBoot, for example, converts the original Spring configuration using XML to using annotations to achieve the same effect. Here are some notes:
- @RestController
- @RequestMapping
- @Configuration
- @SpringBootApplication
- @ConfigurationProperties
Understand the annotation
Annotations can be divided into meta-annotations, built-in annotations and user – defined annotations
Yuan notes
A meta-annotation is a basic annotation that can be applied to other annotations. A meta-annotation is an annotation that marks the annotation.
Meta-annotations are:
- java.lang.annotation.Retention
- java.lang.annotation.Target
- java.lang.annotation.Documented
- java.lang.annotation.Inherited
- java.lang.annotation.Repeatable
- java.lang.annotation.Native
@Retention
Retention means Retention, indicating the time frame in which the annotation occurred. Its value is Java. Lang. RetentionPolicy enumeration.
- Retentionpolicy. SOURCE: useful only at the SOURCE level, discarded at compile time
- Retentionpolicy. CLASS: retained at compile time and discarded at runtime (in the JVM); This is the default retention policy
- Retentionpolicy. RUNTIME: it remains valid at compile time and RUNTIME, so it can be used in reflection
@Retention(RetentionPolicy.RUNTIME)
public @interface Demo {
}
Copy the code
@Documented
Documented indicates the type of annotation that will be included in Javadoc.
@Target
@target indicates the context in which the annotation uses the constraint. It is an array and can be marked for use in multiple scopes. Value by Java. Lang. The annotation. ElementType specified.
Java. Lang. The annotation. ElementType available value is as follows:
- TYPE: declaration of class, interface, annotation, enumeration
- FIELD: member variable, in the declaration of constants containing enumerations
- METHOD: in the declaration of a METHOD
- PARAMETER: a formal declaration of parameters
- CONSTRUCTOR: Declaration of a CONSTRUCTOR
- LOCAL_VARIABLE: declaration of local variables
- ANNOTATION_TYPE: in a declaration of annotation type
- PACKAGE: the declaration of a PACKAGE
- TYPE_PARAMETER: declaration of type parameters (since JDK8)
- TYPE_USE: Use of types (since JDK8)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface Demo {
}
Copy the code
@Inherited
Inherited literally means Inherited. @Inherited is automatically Inherited. Requires that subclasses are not marked by any annotations. Extends is only valid with extends; implementing interfaces are not. Here’s an example:
@Inherited
public @interface Demo {
}
@Demo
public class SuperClass{}public class ChildClass extends SuperClass{}Copy the code
The SuperClass is annotated @demo. The ChildClass inherits the SuperClass and is not annotated with any markup, so the ChildClass inherits the SuperClass annotated @demo.
Equivalent to:
@Demo
public class ChildClass extends SuperClass{}Copy the code
@Repeatable
The meta annotation indicates that the declared annotation can be used multiple times. The @REPEATable attribute requires the annotation’s class. The following is a Demo note to indicate the user role level, SSS– B total of 5 levels.
Note: The Demo annotation was marked with @REPEATable, and role-class was specified as the attribute value, and the Role annotation must have the attribute name value and type as a Demo array.
The following is an example:
@Repeatable(Role.class)
public @interface Demo {
String role(a);
}
public @interface Role {
Demo[] value();
}
public @interface Td {
}
@Demo(role="SSS")
@Demo(role="SS")
@Demo(role="S")
@Demo(role="A")
@Demo(role="B")
public class FK1 {}@Demo(role="SSS")
@Demo(role="SS")
@Demo(role="S")
@Demo(role="A")
@Demo(role="B")
@Td / / error
@Td // Error Td annotations cannot be repeated
public class FK1 {}Copy the code
- Comments that are not marked by @REPEATable cannot appear more than once.
Attributes of annotations
Annotations have only variables (attributes) and no methods, and attributes of annotations are declared as methods with no arguments.
public @interface Demo {
String role(a);
}
Copy the code
The @demo annotation declares an attribute role.
The default value for the property
Use the default keyword after an attribute to set a default value for the attribute.
public @interface Demo {
String role(a) default "B";
}
Copy the code
Use of annotations
If you have only one attribute named value, you can write the attribute value directly in parentheses when using annotations.
public @interface Due {
String value(a);
}
@Due("Hi")
public class FK1 {}/ / equivalent
@Due(value="Hi")
public class FK1 {}Copy the code
Annotations without attributes can only be used under the tag.
public @interface Due {
}
@Due // Just mark it
public class FK1 {}Copy the code
Java built-in annotations
- Deprecated: indicates deprecation and will be warned at compile time.
public class AnnoDemo {
@Deprecated
private static void sayHello(a){}public static void main(String[] args){ AnnoDemo.sayHello(); }}Copy the code
-
FunctionalInterface: a normal interface with a method.
-
Override: a method that an implementation class overrides a parent class or interface
-
SafeVarargs: Parameter safety type annotation to tell developers not to do unsafe things with parameters
-
@SuppressWarnings: Prevents the compiler from issuing an alarm, such as a call to a method that uses the @suppressWarnings flag. SuppressWarnings can be suppressed using @SuppressWarnings
You can view the warning values that can be suppressed using the javac -x command:
C:\Users\BYRON.Y.Y> Javac-x-xlint enables recommended warnings -Xlint:{all,auxiliaryclass,cast,classfile,deprecation,dep-ann,divzero,empty,fallthrough,finally,options,overloads,overri des,path,processing,rawtypes,serial,static,try,unchecked,varargs,-auxiliaryclass,-cast,-classfile,-deprecation,-dep-ann, -divzero,-empty,-fallthrough,-finally,-options,-overloads,-overrides,-path,-processing,-rawtypes,-serial,-static,-try,-u Nchecked,-varargs, None} Enables or disables specific warningsCopy the code
SuppressWarnings:
- All: @SuppressWarnings(“all”) will suppress all warnings
- Cast: Suppress class cast conversion warning
- Deprecation: Suppress Deprecated warnings, such as the possible use of @deprecated
- Divzero: Suppress warnings with a divisor of 0
- Unchecked: Suppress collection expressions that do not specify generics
- Fallthrough: Suppress switch warnings, such as a case without a break statement
- Serial: Suppress warnings that implement the Serializable interface but do not declare the serialVersionUID attribute
- Finally: Suppresses warnings if finally is not used properly, such as not catching an exception, and the compiler issues a warning:
@SuppressWarnings("finally") public String finallyTest(String str) { try { str+="."; } finally { returnstr.toUpperCase(); }}Copy the code
- Overrides: warning to suppress methods that do not override their parent class
Make notes useful
Annotations are only used as markup, and for them to really work, you can use Java reflection to write an annotation parser that is used as a business requirement.
Annotations and Reflection (under java.lang.Reflect)
- Can be achieved by
java.lang.reflect.Class
theisAnnotationPresent()
Find out if there are annotations. - Can be achieved by
<T extends Annotation> T getAnnotation(Class<T> annotationClass)
Method to get the annotation object - Can be achieved by
Annotation[] getAnnotations()
Method to get a list of annotations
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ByronAnno {
String value(a) default "ok";
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ByronAnno {
String value(a) default "ok";
}
Copy the code
Run output: Annotation value is: class
Annotating production cases
Finally, a production case is used to conclude the introduction of annotations.
Example: In the HTTP interface, request parameters are strings, and the request parameters are converted to the request entity class. When you validate a parameter, you need to check whether certain fields are null and verify the size of an integer value.
ValidateVal annotation class
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidateVal {
String length(a) default "";
boolean isBeNull(a) default false;
boolean isNotcheckDecimal(a) default false;// Verify decimals
int isJudgeLength(a) default 0; // 0: no judgment 1: fixed value 2: interval
int minLength(a) default 0;
int maxLength(a) default 20;
int minValue(a) default 0;
int maxValue(a) default Integer.MAX_VALUE;
String expression(a) default "";
String errorMsg(a) default "";
int neeDivided(a) default 1; // Whether multiple is required
If yes =true, if no =false
boolean isCheckNumber(a) default false;
}
Copy the code
Parsing method used to parse @validatEval annotations
protected <T> T validateAndConvert(String param, Class<T> cla) throws Exception {
T t = JSONUtils.json2Object(param, cla);
if (t == null) {
// Throw an exception
}
Field[] fields = t.getClass().getDeclaredFields();
Field[] parentFields = t.getClass().getSuperclass().getDeclaredFields();
List<Field> allFields = Lists.newArrayList(fields);
allFields.addAll(Arrays.asList(parentFields));
for (Field f : allFields) {
f.setAccessible(true);
ValidateVal an = f.getAnnotation(ValidateVal.class);
String fieldName = f.getName();
if (an == null) {
String value = String.valueOf(f.get(t));
value = value.trim();
if (f.getType().equals(String.class)) {
f.set(t, value);
}
if (value == null || value.equals("") || value.equals("null")) {
// Throw an exception}}else {
if (f.getType().equals(String.class)) {
String value = null;
if(f.get(t) ! =null) {
value = String.valueOf(f.get(t));
value = value.trim();
f.set(t, value);
}
if(! an.isBeNull()) {if (value == null || value.equals("") || value.equals("null")) {
// Throw an exception}}else {// Set the null string to null
if (value == null || value.equals("") || value.equals("null")) {
f.set(t, null); }}if(! an.expression().equals("")) {
Pattern pattern = Pattern.compile(an.expression());
Matcher matcher = pattern.matcher(value);
if(! matcher.matches()) {// Throw an exception}}if (an.isJudgeLength() == 1) { / / setting value
String[] lengthArr = an.length().split(",");
boolean in = false;
for (int i = 0; i < lengthArr.length; i++) {
if (value.length() == Integer.parseInt(lengthArr[i])) {
in = true; }}if(! in) {// Throw an exception}}else if (an.isJudgeLength() == 2) {
int min = an.minLength();
int max = an.maxLength();
if (value.length() < min || value.length() > max) {
// Throw an exception}}}else if (f.getType().equals(Integer.class)) {
if (f.get(t) == null) {
if (an.isBeNull()) {
f.set(t, null);
continue;
} else {
// Throw an exception
}
}
Integer value = Integer.valueOf(f.get(t).toString());
if(an.neeDivided() ! =1&& value % an.neeDivided() ! =0) {
// Throw an exception
}
if (value < an.minValue() || value > an.maxValue()) {
// Throw an exception}}}}return t;
}
Copy the code
References:
- SuppressWarnings values: http://blog.bangbits.com/2008/05/suppresswarnings-annotations.html