reflect反射 & Annotation注解,
reflect反射 & Annotation注解,
类加载器的基本概念:
类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机
使用 Java 类的方式如下:Java 源程序(.java )在经过 Java 编译器编译之后就被转换成
Java 字节代码(.class )。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类
的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就
可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工
具动态生成的,也可能是通过网络下载的。
Java反射机制定义:
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调
用对象的方法的功能称为java语言的反射机制。
Java 反射机制的功能:
1.在运行时判断任意一个对象所属的类。
2.在运行时构造任意一个类的对象。
3.在运行时判断任意一个类所具有的成员变量和方法。
4.在运行时调用任意一个对象的方法。
5.生成动态代理。
Java 反射机制的应用场景:
1.逆向代码 ,例如反编译
2.与注解相结合的框架 例如Retrofit
3.单纯的反射机制应用框架 例如EventBus
4.动态生成类框架 例如Gson
常见的注解:
注解的概念是在jdk5.0中提出来的,在java.lang的包中已经定义了三个注解:
Override,Deprecated,SuppressWarnings
Override相信大家非常熟悉,就是表明这个方法是改写了父类的方法,重写
Deprecated表示在新版本的 jdk中已经不建议使用这个方法或者属性,不建议使用
SuppressWarning就是屏蔽掉一些警告,压制警告
注解的概念:
注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的
一部分。注解对于代码的运行效果没有直接影响。
注解有许多用处,主要如下:
- 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
- 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它
相应处理。
- 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取
元注解:
元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它
的注解上面。
如果难于理解的话,你可以这样理解。元注解也是一张标签,但是它是一张特殊的标签,它
的作用和目的就是给其他普通的标签进行解释说明的。
元标签有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5种。
保留、 文档、 目标、 继承、 可重复的
@Retention注解的三种取值 - RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 |
@Target注解的取值 ElementType.ANNOTATION_TYPE 可以给一个注解进行注解 |
@Inherited注解的用法 注解 TestInherited 被 @Inherited 修饰,之后类 A 被 TestInherited 注解,类 B继承 A,类 B 也拥有 TestInherited 这个注解。 |
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER,
TYPE})
public @interface Deprecated {
}
元注解:
Target注解的功能就是表明你这个注解是用在什么地方的,它的值是一个枚举型
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
Retention注解的功能差不多说明的就是你的注解的生命周期吧,就是什么时候失效,它的值如下
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
注解的属性:
注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义
中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该
成员变量的类型。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interfaceTestAnnotation{
int id();
String msg();
}
意思是: TestAnnotation 这个注解中拥有 id 和 msg 两个属性。在使用的时候,我们应该给它们进行赋值。
Android中通过注解FindViewByID:自定义模仿ButterKnife(通过反射、注解的方式绑定控件)
自定义ButterKnife注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
@IdRes int value() default View.NO_ID;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindString {
@StringRes int value() default View.NO_ID;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnClick {
@IdRes int[] value();
}
public class ButterKnife {
public static void bind(final Activity activity) {
// 1. 拿到类模板
Class<Activity> clazz = (Class<Activity>) activity.getClass();
// 2. 拿到所有的属性
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
// 判断是否被对应的注解修饰
if (field.isAnnotationPresent(BindView.class)) {
// 拿到修饰该属性的注解
BindView bindView = field.getAnnotation(BindView.class);
int id = bindView.value();
// 根据id拿到xml中的控件对象
View view = activity.findViewById(id);
// 给属性赋值
try {
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 绑定字符串
*/
if (field.isAnnotationPresent(BindString.class)) {
BindString bindString = field.getAnnotation(BindString.class);
int value = bindString.value();
String string = activity.getResources().getString(value);
try {
field.set(activity, string);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
// 删除线的文字
if (field.isAnnotationPresent(Deprecated.class)) {
Deprecated deprecatedAnnotation = field.getAnnotation(Deprecated.class);
int value = deprecatedAnnotation.value();
View view = activity.findViewById(value);
if (view instanceof TextView) {
((TextView) view).getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
try {
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
/**
* 绑定点击事件
*/
Method[] declaredMethods = clazz.getDeclaredMethods();
for (final Method method : declaredMethods) {
method.setAccessible(true);
if (method.isAnnotationPresent(OnClick.class)) {
OnClick onClickAnnotation = method.getAnnotation(OnClick.class);
int[] ids = onClickAnnotation.value();
for (int id : ids) {
View view = activity.findViewById(id);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
method.invoke(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}
相关文章
- 暂无相关文章
用户点评