java中注解与反射运用及实现

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-29 14:19   945   0

注解也算是常用的,但大多都是用用,并不能明白很多细节及原理;

我通过注解和反射来模拟一个ButterKinfe场景

先说说注解

通过@interface ,@Target(),@Retention,要描述

如:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
    @IdRes int value();
}

@Target() @Retention() 表示注解上的注解,简单来说他们也是注解,对下面刚创建的这个注解进行声明

@Target() 表示声明这个注解在那些节点上使用;它有三个值

RetentionPolicy.SOURCE

标记的注解仅保留在源级别中,并被编译器忽略。

RetentionPolicy.CLASS

标记的注解在编译时由编译器保留,但 Java 虚拟机(JVM)会忽略。意思是在编译成javac时就会使用它,把它代码注入到字节中;

RetentionPolicy.RUNTIME

标记的注解由 JVM 保留,因此运行时环境可以使用它

SOURCE < CLASS < RUNTIME,即CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS。

它们运用场景:

SOURCE:源码,场景 APT,在编译时获取到注解及注解的声明的类,及所有成员信息,类似于编译器场景;

CLASS:字节码,场景 字节码增强,在编译出Class后,通过修改Class数据以实现修改代码逻辑目的。对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解。

RUNTIME:运行时,场景 反射;在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判定。

反射:

正常情况下我们是new 对象实例,进行使用它的方法属性;但不知道这个对象是什么,就可以用反射;

反射就是在运行状态中,通过任意一个类,通过反射知道这个类及属性和方法;

getFied()和getDeclareField()的区别,前者是获取到的是当类及父类的属性;getDeclaredFiled()获取到是当前属性,获取不到父类的属性;

这两个实例代码:

创建一个InjectUtils.class

public class InjectUtils {

    public static void injectView(Activity activity){
        Class<? extends Activity> className = activity.getClass();

        Field[] fields = className.getDeclaredFields();

        for(Field f : fields){
            //判断属性上有InjectView 的注解
            if (f.isAnnotationPresent(InjectView.class)){
                //获取注解器
                InjectView injectView = f.getDeclaredAnnotation(InjectView.class);
                //通过注解获取当前属性中设置的值
                int id =  injectView.value();
                //通过在activity 中设置的id,查找View
                View view = activity.findViewById(id);
                //反射设置,属性值;设置访问权限,允许操作private的属性
                f.setAccessible(true);
                try {
                    //反射赋值,把获取到的view,赋值到activity 中属性中
                    f.set(activity,view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

创建一个注解:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView {
    @IdRes int value();
}

MainActivity中使用:

    @InjectView(R.id.tv_name)
    private TextView tvName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InjectUtils.injectView(this);

        tvName.setText("Inject Success!");
    }

java注解(annotation)有称为java标注,是JDK1.5引入的一种注释机制。提供有关于程序但不属于程序本身的数据。注解对它们注解的代码操作并没有直接的影响;

注解单独用没有多大的意义;

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP