定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用分类:
①编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
② 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
③编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
一、自定义注解
注解的声明跟接口的声明类似,不同的是注解需要在interface前添加@,如下代码:
package com.ishow.xutils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by huangxuanheng on 2015/9/20
*/
@Retention(RetentionPolicy.RUNTIME) //声明该注解是在运行时
@Target(ElementType.FIELD) //声明注解用于字段的声明
public @interface Inject {
int value(); //声明一个int值的属性
String name(); //声明一个String类型的属性
}
说明:在注解上也可以使用其他注解,自定义的注解的成员可以是基本数据类型,也可以是String 类型、注解类型、枚举类型等。
二、使用反射方式获取注解
package com.ishow.xutils;
import android.app.Activity;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Created by Administrator on 2015/9/20.
*/
public class XUtils {
/**
*为activity相关含有注解Inject的控件属性进行实例化
* @param handle
*/
public static void inject(Activity handle) {
//获取对象handle的字节码,用于获取对象的相关属性和注解
Class<Activity> handleClass = (Class<Activity>) handle.getClass();
Field[] fields = handleClass.getDeclaredFields();
for(Field field :fields){
//判断对应注解是否是该属性的注解,如果是,则获取该注解的值,设置给该属性
if(field.isAnnotationPresent(Inject.class)){
Inject annotation = field.getAnnotation(Inject.class);
field.setAccessible(true);
try {
Method findViewById = getDeclaredMethod(handleClass,"findViewById", int.class);
findViewById.setAccessible(true);
Object obj=findViewById.invoke(handle,annotation.value());
field.set(handle,obj);
} catch (Exception e) {
System.out.print(e.getMessage());
}
}
}
}
/**
* 使用递归获取方法对象
* 根据指定的字节码对象和指定方法名称及该方法对应的参数类型,获取该方法或者父类中的具有名称为name的方法对象
*/
private static Method getDeclaredMethod(Class<?>handleClass,String name ,Class<?>... parameterTypes){
Method method=null;
try {
method = handleClass.getDeclaredMethod(name, parameterTypes);
return method;
} catch (NoSuchMethodException e) {
return getDeclaredMethod(handleClass.getSuperclass(), name, parameterTypes);
}
}
}
三、使用注解
package com.ishow.huangxuanheng;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.ishow.xutils.Inject;
import com.ishow.xutils.XUtils;
public class MainActivity extends AppCompatActivity {
@Inject(R.id.tv)
private TextView tv; //为属性tv定义注解
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//通过调用inject方法为属性tv进行findViewById注册
XUtils.inject(this);
//注册了tv,就可以直接调用tv对象的所有方法了
tv.setText("hello android ,i love you!!");
}
}
本例主要是通过反射,获取到对应activity类中定义的属性Field,再通过判断该属性是否声明有指定的注解,如果有,则通过反射获取activity中的方法findViewById对该属性进行注册到activity中,注册完成后,再调用其相应方法完成相关工作。