美文网首页
JAVA中的注解

JAVA中的注解

作者: Jon_Snow09 | 来源:发表于2018-08-12 23:12 被阅读0次

abstract

  • 什么是java中的注解
  • 注解的定义
  • 自定义一个注解

什么是java中的注解

注解提供了一种安全的类似注释的机制.用来将 任何的信息或者元数据 (metadata)与程序元素( 类,方法,成员变量等 )进行关联,为程序的元素加上更加直观的说明,这些说明信息与程序的业务逻辑无关,是由 指定的工具或框架 来实现的.Annotation像修饰符一样,应用于包,类型构造方法,方法,成员变量,参数,及本地变量的声明语句中.

注解的定义

先看下面的例子

//下面两个是必须的元注解,分别确定了这个注解的作用对象(类的方法)和生命周期(这个注解会被保存在class文件中,并且直到运行时也不会被丢弃)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    //此处定义了注解可以接受一个数据类型为int的元数据
    int value();
}

所以,定义一个注解分为三步

  1. 跟类(class),接口(interface),枚举(enum)一样,注解的定义有自己的关键字(@interface)
  2. 定义注解时需要元注解的定义(之前已经提到过了,注解作用的对象是类,方法,成员变量等,那么元注解作用的对象就是注解本身),一般有下面几个元注解
  • @Target 用来标注注解的作用对象,是类,方法,还是成员变量
  • @Retention 用来标注注解的生命周期,有三种 1.RetentionPolicy.SOURCE,表示这个注解只出现在源码中,编译时会被编译器抛弃 2.RetentionPolicy.CLASS,这种是注解的默认状态,表示这个注解会被保存到class文件中,但是到了runtime就会被抛弃 3.RetentionPolicy.RUNTIME,这表示注解会保留到运行时
  • @Documented 它的作用是能够将注解中的元素包含到Javadoc中去
  • @Inherited Inherited 是指继承,@Inherited 定义了一个注释与子类的关系。如果一个超类带有 @Inherited 注解,那么对于该超类,它的子类如果没有被任何注解应用的话,那么这个子类就继承了超类的注解
  • @Repeatable 用这个元注解修饰之后,注解可以重复赋值

3.最后,需要在注解内部定义方法,接收使用注解时在注解后面的赋值

自定义一个注解

现在我们举个栗子,自定义一个简单的butterknife注解,实现两个功能,一是直接注解成员变量得到控件的对象,而是直接成员方法得到控件的点击事件

获取控件引用的注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindClick {
    int value();
}

绑定点击事件的注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface BindView {
    //此处定义了注解可以接受一个数据类型为int的元数据
    int value();
}

最重要的一个类,读取这两个注解的值,并且将其实现的框架类,通过注入一个activity对象,就可以解析所有activity里面的注解,并完成相应的功能

public class ButterKnife {
    public static void inject(Activity activity) {
        Class<? extends Activity> clazz = activity.getClass();

        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.isAnnotationPresent(BindView.class)) {
                BindView annotation = field.getAnnotation(BindView.class);
                int resId = annotation.value();
                field.setAccessible(true);
                try {
                    field.set(activity, activity.findViewById(resId));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            if (method.isAnnotationPresent(BindClick.class)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    BindClick declaredAnnotation = method.getDeclaredAnnotation(BindClick.class);
                    int resId = declaredAnnotation.value();
                    method.setAccessible(true);
                    View viewById = activity.findViewById(resId);
                    viewById.setOnClickListener(v -> {
                        try {
                            method.invoke(activity, v);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    });
                }
            }
        }
    }
}

最后一步,在activity中编写相应的注解,并且调用ButterKnife.inject(this)就可以了

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv_title)
    TextView tvTitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.inject(this);
        tvTitle.setText(getResources().getString(R.string.app_name));
    }

    @BindClick(R.id.tv_title)
    public void onTitleClick(View view) {
        Toast.makeText(this, getResources().getString(R.string.app_name), Toast.LENGTH_SHORT).show();
    }
}

相关文章

网友评论

      本文标题:JAVA中的注解

      本文链接:https://www.haomeiwen.com/subject/oviebftx.html