Annotations and Reflection
Annotations
Annotations are used to sign some methods or classes and so on, they are not only can mention the programmer, but also can work on your code if you used correct form.
Internal Annotations from JDK
@Override // It's used to sign the methods form super class, and it can restrict(限制) that method is changed in a wrong way.
@Deprecated // It's used to remind coder that this method has some bad places, or is nor recommended. It's also used to remind coder to use another better methods to realize their purpose.
@SuppressWarnings // It's used to eliminate(消除) warnings. It accepts a param, the details can be looked up in the documentation.
Meta-annotations(元注解)
Meta-annotations are a kind of the basic annotations, they are used to express the usage(用途) of a complex user-defined annotation, such as where can use, and when they lose their effects.
@Target // Describe the user-defined annotation where it can use, such as method, class, field, constructor and so on. It accept a param, a String or an Array, which express the effect range. At most of the time, it's usually ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE, ElementType.ANNOTATION_TYPE, ElementType.PACKGE.You can search the JDK source code or document for more details.
@Retention // Describe the user-defined annotation when it loses its effect. It accept a param, which should be chosen in RetentionPolicy.SOURCE/CLASS/RUNTIME. The details can be looked up in the documentation.
// RetentionPolicy.SOUCE:
// When code is compiled, and target classes have been generated(生成), the effect will disappear.
// RetentionPolicy.CLASS:
// The annotation will still work on target classes. However, when the program run, it won't work.
// RetentionPolicy.RUNTIME:
// The annotation will work at all time(总是).
@Document // Express that the annotation should be included in the javadoc.
@Inherited // It aims that the subclasses can inherite the super class.
How to customize a annotation?
/**
* explanation
*/
@Target(...)
@Retention(...)
@Document(...)
@Inherited(..)
(public) @interface [annotation name] {
// params list pattern:
// default rule: if the params have only one, its name probably is 'value'.
[type] [param name] + () + default [default value];
}
Reflection
Java reflection allows program get any class's information by Reflection API when the program is running. And it can operate any object's inner attributes and methods directly. It's the key mechanism(机制) that let Java be a dynamic programming language.
Where can it reply?
Advantages and Shortcomings
- Advantages
Reflection can create Object and compile dynamically, it provide the flexibility(灵活性) of creating a project.
- Shortcomings
Using Reflection too much will extremely reduce performance.
Main APIs
java.lang.Class
+
java.lang.reflect.Method ...
How get the class and new a object?
Premise(前提) Class:
package com.tinysnow.Java.MultipurposeClasses;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author TinySnow
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String username;
private int age;
private String email;
private String password;
private String[] hobbies;
private String[] relatives;
}
Get class example:
package com.tinysnow.Java.AnnotationsAndReflection;
import java.lang.reflect.Field;
/**
* @author TinySnow
*/
public class GetReflectedClass {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class aClass = Class.forName("com.tinysnow.Java.MultipurposeClasses.User");
Field username = aClass.getDeclaredField("username");
System.out.println(username);
}
}
- Result:
The other ways to get class can be looked up in the first and second photos at the end of this passage, "Appendix".
Invoke the method through reflection:
Some thing about setAccessible()
if the setAccessible() method is on, the efficiency(效率) will be very low, here is a result that compared with turning off setAccessible() and common way:
common way: new an object.
Get object example:
package com.tinysnow.Java.AnnotationsAndReflection;
/**
* @author TinySnow
*/
public class GetReflectedObject {
public static void main(String[] args) {
try {
Class aClass = Class.forName("com.tinysnow.Java.MultipurposeClasses.User");
aClass.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
==Attention Please:==
The object that comes from the "newInstance" method is a full null object, that is all attributes in the object will be evaluated(赋值) with null, 0, "" and so on.
If you wanna new an object with some attributes or params, please invoke(调用) "getConstructor" or "getDeclaredConstructors" and then use the constructor to new an object you want.
An example for the above explanation:
package com.tinysnow.Java.AnnotationsAndReflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author TinySnow
*/
public class GetReflectedObject {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class aClass = Class.forName("com.tinysnow.Java.MultipurposeClasses.User");
Constructor constructor = aClass.getDeclaredConstructor(int.class, String.class,
int.class, String.class, String.class, String[].class, String[].class);
Object test = constructor.newInstance(1, "真中あお", 114, "ao@514.com", "1919810",
new String[]{"23", "编曲"}, new String[]{"someone"});
System.out.println(test.toString());
}
}
- Result:
About the generic(泛型):
Some place needed memory:
- getXxxxx() : Can only read the public attributes, methods, constructors and so on.
- getDeclardXxxxx() : Can read all things although someone is private.
All the types that own a class
By the way, the class of array is complicated, so here gives an example:
Manipulate(操作) annotations through reflection
The approach is almost the same as operating generic. So here only gives an example. If you wanna manipulate generic, please change the method name and params.
package com.tinysnow.Java.AnnotationsAndReflection;
import lombok.Data;
import java.lang.annotation.*;
import java.util.Arrays;
/**
* @author TinySnow
*/
@Data
@TestAnnotation("baka")
public class OperateAnnotationsThroughReflection {
public static void main(String[] args) {
OperateAnnotationsThroughReflection reflection =
new OperateAnnotationsThroughReflection();
Class aClass = reflection.getClass();
Annotation[] annotations = aClass.getAnnotations();
System.out.println(Arrays.toString(annotations));
// The way to get the value in the annotation
String value = aClass.getAnnotation(TestAnnotation.class).value();
System.out.println(value);
}
}
/**
* @author TinySnow
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation{
String value() default "Tessa baka";
}