注解
注解的作用或者意义是什么
注解本身没有任何意义,单独的注解就是一种注释,他需要结合其他如反射、插桩等技术才有意义。
java注解又称java标注,是JDK1.5引入的一种注释机制。是元数据的一种形式,提供有关于程序但不属于程序本身的数据。注解对他们注释的代码的操作没有直接影响。
元注解:注解上的注解
声明的注解允许作用于哪些节点使用@Target声明:保留级别由@Retention声明。其中保留级别如下。
RetentionPolicy.SOURCE:标记的注解仅保留在原级别中,并被编译器忽略。
RetentionPolicy.CLASS: 标记的注解在编译时由编译器保留,但Java虚拟机(JVM)会忽略。
RetentionPolicy.RUNTIME: 标记的注解由JVM保留,因此运行时环境可以使用它。
元注解有哪些
(1)@Retention:定义注解的保留策略。
(2)@Target: 定义注解的作用目标。
- CONSTRUCTOR: 用于描述构造器
- FIELD:用于描述域即类成员变量
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口或enum声明
- TYPE_PARAMETER:1.8版本开始,描述类、接口或enum参数的声明
- TYPE_USE:1.8版本开始,描述一种类、接口或enum声明
(3)@Document:说明该注解将被包含在javadoc中
(4)@Inherited:说明子类可以继承父类中的该注解
用于表示某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
APT:
Annotation Processor Tools
怎么运行:
.java->javac->.class
采集到所有的注解信息->Element->注解处理程序
Indef:
语法检查: IDE实现的,IDE插件实现的
字节码增强:
在字节码中写代码
.class-> 格式 数据按照特定的方式记录与排序
注解的应用场景
级别 | 技术 | 说明 |
---|---|---|
源码 | APT | 在编译期能够获取注解与注解声明的类包括类中所有成员信息,一般用于生成额外的辅助类 |
– | – | – |
字节码 | 字节码增强 | 在编译除Class后,通过修改Class数据以实现修改代码逻辑目的。对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解 |
– | – | – |
运行时 | 反射 | 在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定 |
反射
注解+反射:自动完成findViewById
Filed:获得自己+父类的成员(不包括private)
DecleredFile:只能获得自己的成员(不包括父类,所有作用域)
下面来一个小小的实战:
public class InjectUtil {
public static void injectView(Activity activity) {
Class<? extends Activity> cls=activity.getClass();
//获取此类所有的成员
Field[] declaredFields=cls.getDeclaredFields();
for(Field declaredField:declaredFields){
if(declaredField.isAnnotationPresent(InjectVIew.class)){
InjectVIew injectVIew=declaredField.getAnnotation(InjectVIew.class);
//获得了注解中设置的id
int id=injectVIew.value();
View view=activity.findViewById(id);
//反射设置属性的值
declaredField.setAccessible(true);
try {
declaredField.set(activity,view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectVIew {
@IdRes int value();
}
public class MainActivity extends AppCompatActivity {
@InjectVIew(R.id.tv)
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtil.injectView(this);
tv.setText("xixi");
}
}