1.什么是注解
定义:注解是代码里的特殊标记,可以在编译、类加载、运行时被读取,并执行相应的处理。只是一个标记,并没有逻辑操作
使用场景: 一般都配合反射、apt、aop等,
2.注解分类
注解分为标准注解和元注解
2.1标准注解
- @Override 对覆盖超类中的方法进行标记,如果被标记的方法并没有覆盖超类中的方法,编译器会发出错误警告。(为什么呢?往下看)
- @Deprecated:对不鼓励使用或者已过时的方法添加注解。
- @Suppress Warnings: 选择性取消特定代码段警告
- @ SafeVarargs: JDK7 新增,用来使用可变长度参数的方法,其在与泛型类一起使用不会出现类型安全问题。
一般常见第一种和第二种。
2.2 元注解
用于创建新的注解。
- @Targe: 注解所修饰的对象范围 (自己新建注解,常用)
- @Retention : 用来声明注解的保留策略 (自己新建注解,常用)
- @Inherited:表示注解可被继承
- @Documented: 表示这个注解应该被JavaDoc工具记录
- @Repeatable:jdk 8 新增,允许一个注解在同一个声明类型(类、属性或方法)上多次使用
其中@Targe注解取值是一个ElementType数组,而ElementType是一个枚举。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
// 修饰类,接口,或枚举类型
TYPE,
/** Field declaration (includes enum constants) */
//修饰成员变量
FIELD,
/** Method declaration */
// 修饰方法
METHOD,
/** Formal parameter declaration */
//修饰参数
PARAMETER,
/** Constructor declaration */
// 修饰构造方法
CONSTRUCTOR,
/** Local variable declaration */
// 修饰局部变量
LOCAL_VARIABLE,
/** Annotation type declaration */
// 修饰注解
ANNOTATION_TYPE,
/** Package declaration */
// 修饰包
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
// 类型参数说明
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
//使用类型
TYPE_USE
}
其中@Retention 注解取值是一个RetentionPolicy值,而RetentionPolicy是一个枚举
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
- RetentionPolicy.SOURCE :源码级注解,注解信息只会保留在.java源码中,源码在编译后,注解信息被丢弃,不会保留在.class种
- RetentionPolicy.CLASS :编译时注解,注解信息会保留在.java源码以及.class种,当运行java程序种,JVM会丢弃该注解信息,不会保留在JVM种
- RetentionPolicy.RUNTIME:运行时注解,当运行Java程序时,JVM也会保留该注解信息,可通过反射获取该注解信息
@Override为标记的方法并没有覆盖超类中的方法,编译器会发出错误警告? 因为Retention注解时源码级的,所以编译器会去检测。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
就拿findViewById来说 通过注解+反射来注入
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
int value();
}
@BindView(R.id.tv_text)
TextView textView;
public class ViewUtils {
public static void inject(Activity activity) {
Field[] fields = activity.getClass().getDeclaredFields();//反射获取该对象的所有方法
for (Field field : fields) {
BindView bindView = field.getAnnotation(BindView.class);
if (bindView != null) {
View view = activity.findViewById(bindView.value());
field.setAccessible(true);
try {
//activity 所在类 ,view值 注入
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
使用
public class BindViewActivity extends AppCompatActivity {
@BindView(R.id.tv_text)
TextView textView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewUtils.inject(this);
textView.setText("hahhah");
}
}