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

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

我通过注解和反射来模拟一个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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值