注解机制(初级用法) - 1835434698/1835434698.github.io GitHub Wiki
注解(Annotation)
一、内置注解
在Java中常见的内置注解的如下:
@Override:表示被标记的方法继承了父类同名同参的方法,当检测到父类不存在该方法时将报编译时异常。
@Deprecated:表示被标记的方法已不推荐使用。
@SuppressWarnings():将提示编译器忽略当前被标记方法中的Warnings
二、元注解
元注解其实就是注解的规范,也就是来约束定义注解的用法(就像是语法),但是它本身又是一个注解。(就像Android的zygote进程一样,孵化出各种各样的进程[如图])
-
@Retention
表示被修饰的注解将要保留的阶段。它有三个取值
- RententionPolicy.SOURCE:将保留至源码阶段。编译时将隐藏
- RententionPolicy.CLASS:将保留至class文件阶段。但对运行对虚拟机隐藏
- RententionPolicy.RUNTIME:可保留至运行时。
一般我们都选择保留至RUNTIME
-
@Documented
表示被修饰的注解将会记入api文档
-
@Inherited
表示被修饰的注解将会被自动继承
-
@Target
表示被修饰的注解将要被作用的位置。它有三个常见取值
- ElementType.TYPE:可作用于类
- ElementType.FIELD:可作用于成员变量
- ElementType.METHOD:可作用于成员方法
三、自定义注解
下面我们开始尝试自定义并使用注解:
1、最简单的注解类
/**
* 定义注解
*/
@Retention(RetentionPolicy.RUNTIME)//注明保留阶段
public @interface Kevin {//自定义注解用 @interfac修饰
String name() default "kevin";
}
/**
* 使用注解修饰
*/
@Kevin(name = "12345")
public class Test {
}
/**
* 处理注解
*/
public class TestClass {
public static void showKevin(Class c) {
Log.d("注解", "c.name() = "+c.getName());
boolean isExist = c.isAnnotationPresent(Kevin.class);//使用class方法检测是否是注解类
if (isExist) {
//通过实体类解析其注解,得到注解实体对象
Kevin kevin = (Kevin) c.getAnnotation(Kevin.class);
Log.d("注解", "kevin.name() = "+kevin.name());//得到注解志
}
}
public static void main(String[] args) {
showKevin(Test.class);//调用
}
}
/**
* {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
if (annotationClass == null) {
throw new NullPointerException("annotationClass == null");
}
if (isDeclaredAnnotationPresent(annotationClass)) {
return true;
}
if (annotationClass.isDeclaredAnnotationPresent(Inherited.class)) {
for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
if (sup.isDeclaredAnnotationPresent(annotationClass)) {
return true;
}
}
}
return false;
}
2、指定修饰的注解
/**
* 注解类
*/
@Target(ElementType.TYPE)//注明修饰目标只能是类
@Retention(RetentionPolicy.RUNTIME)//注明保留阶段
public @interface MyClassAnnotation {
String uriClass();
String descClass();
}
/**
* 使用注解修饰
*/
@MyClassAnnotation(descClass = "The Class", uriClass = "com.sgl.annotation")
public class TestAnnotation {
}
/**
* 理注解
*/
public static <T> void parseType(Class<T> clazz) {
try { //通过实体类解析其注解,得到注解实体对象
MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);
if (myClassAnnotation != null) {
Log.d("注解", " class uri: " + myClassAnnotation.uriClass());
Log.d("注解", " class desc: " + myClassAnnotation.descClass());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
parseType(TestAnnotation.class);
}
3、指定修饰的注解(应用到类和方法上)
/**
* 可以同时应用到类和方法上
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyClassAndMethodAnnotation {
// 定义枚举
public enum EnumType {
util, entity, service, model
}
// 设置默认值
public EnumType classType() default EnumType.util;
// 数组
int[] arr() default { 3, 7, 5 };
String color() default "blue";
}
/**
* 使用注解修饰
*/
@MyClassAnnotation(descClass = "The Class", uriClass = "com.sgl.annotation")
@MyClassAndMethodAnnotation(classType = EnumType.entity)
public class TestAnnotation {
}
public static <T> void parseType(Class<T> clazz) {
try { //通过实体类解析其注解,得到注解实体对象
MyClassAndMethodAnnotation myClassAndMethodAnnotation = clazz
.getAnnotation(MyClassAndMethodAnnotation.class);
if (myClassAndMethodAnnotation != null) {
if (EnumType.util.equals(myClassAndMethodAnnotation.classType())) {
Log.d("注解", "this is a util class");
} else if (EnumType.entity.equals(myClassAndMethodAnnotation.classType())){
Log.d("注解", "this is a entity class");
} else {
Log.d("注解", "this is a other class");
}
}
MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);
if (myClassAnnotation != null) {
Log.d("注解", " class uri: " + myClassAnnotation.uriClass());
Log.d("注解", " class desc: " + myClassAnnotation.descClass());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
parseType(TestAnnotation.class);
}
4、方法注解与字段注解
/**
* 方法注解
*/
@Target(ElementType.METHOD)//修饰类型
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMethodAnnotation {
String uriMethod();
String descMethod();
}
/**
* 字段注解
*/
@Target(ElementType.FIELD)//修饰类型
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFieldAnnotation {
String uriField();
String descField();
}
@MyClassAnnotation(descClass = "The Class", uriClass = "com.sgl.annotation")
@MyClassAndMethodAnnotation(classType = EnumType.entity)
public class TestAnnotation {
@MyFieldAnnotation(descField = "The Class Field", uriField = "com.sgl.annotation#id")
private String id;
public TestAnnotation() {
}
public String getId() {
return id;
}
@MyMethodAnnotation(descMethod = "The Class Method", uriMethod = "com.sgl.annotation##setId")
public void setId(String id) {
Log.d("注解", "setId id = "+id);
this.id = id;
}
@MyMethodAnnotation(descMethod = "The Class Method sayHello", uriMethod = "com.sgl.annotation##sayHello")
public void sayHello(String name) {
if (name == null || name.equals("")) {
Log.d("注解", "hello world!");
} else {
Log.d("注解", name + "\t:say hello world");
}
}
}
/**
* 解析方法注解
*
* @param clazz
*/
public static <T> void parseMethod(Class<T> clazz) {
try {
T obj = clazz.newInstance();
for (Method method : clazz.getDeclaredMethods()) {
MyMethodAnnotation methodAnnotation = method.getAnnotation(MyMethodAnnotation.class);
if (methodAnnotation != null) {
Log.d("注解", "methodAnnotation.uri() = "+methodAnnotation.uriMethod());
// 通过反射调用带有此注解的方法
method.invoke(obj, methodAnnotation.uriMethod());
}
MyClassAndMethodAnnotation myClassAndMethodAnnotation = method
.getAnnotation(MyClassAndMethodAnnotation.class);
if (myClassAndMethodAnnotation != null) {
if (EnumType.util.equals(myClassAndMethodAnnotation.classType())) {
Log.d("注解", "this is a util method");
} else {
Log.d("注解", "this is a other method");
}
Log.d("注解", Arrays.toString(myClassAndMethodAnnotation.arr()));// 打印数组
Log.d("注解", myClassAndMethodAnnotation.color());// 输出颜色
}
Log.d("注解", "\t\t-----------------------");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static <T> void parseField(Class<T> clazz) {
try {
// 获得字段注解
Field field = null;// 暴力获取private修饰的成员变量
field = clazz.getDeclaredField("id");
MyAnnotation.MyFieldAnnotation myFieldAnnotation = field.getAnnotation(MyAnnotation.MyFieldAnnotation.class);
Log.d("注解", myFieldAnnotation.descField() + "+" + myFieldAnnotation.uriField());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
parseMethod(TestAnnotation.class);
parseField(TestAnnotation.class);
}
四、注解本质
注解的本质就是给类、方法、字段启了一个别名。