注解

自定义注解及注解的使用

2019-10-09  本文已影响0人  安仔夏天勤奋

注解简介

注解的英文就是 Annotation,是在JDK 1.5之后引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

注解就是给 java 代码加上一个标识规则,javac编译器在编译时就会去检测应用了该注解类的类是否符合标识规则,来约束编码规范。

元注解

Java目前只内置了三种标准注解,以及四种元注解。

1、@Target
表示支持注解的程序元素的种类,注解该用于什么地方,ElementType 注解修饰的元素类型,使用ElementType枚举类来表示:

CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:  包声明
PARAMETER:参数声明
TYPE:类,接口(包括注解类型)或enum声明
ANNOTATION_TYPE:注解类型声明
TYPE_PARAMETER:类型参数声明  从jdk1.8开始  、 hide1.8
 TYPE_USE:类型的使用 从jdk1.8开始 、 hide1.8

2、@Retention
表示保留时间的长短,需要在什么级别保存该注解信息, RetentionPolicy参数包括:

SOURCE:注解将被编译器丢弃。
CLASS:注解在class文件中可用,但会被VM丢弃。
RUNTIME:VM将在运行期也保留注解,因此可通过反射机制读取注解的信息。

RetentionPolicy 它是枚举类,分别简单了解三种类型:

3、@Documented
将此注解包含在Javadoc中。 表示使用该注解的元素应被javadoc或类似工具文档化,它应用于类型声明,类型声明的注解会影响客户端对注解元素的使用。如果一个类型声明添加了Documented注解,那么它的注解会成为被注解元素的公共API的一部分。

4、@Inherited
允许子类继承父类中的注解。表示一个注解类型会被自动继承,如果用户在类声明的时候查询注解类型,同时类声明中也没有这个类型的注解,那么注解类型会自动查询该类的父类,这个过程将会不停地重复,直到该类型的注解被找到为止,或是到达类结构的顶层(Object)。

在开发中最最常用几个注解

通过例子验证如何使用注解

通过编写代码,更能了解注解,对注解的概念更能清楚。首先,编写一个自定义注解类BindView

/**
 * @Author lu an
 * Create Date is  2019/10/9
 * Des  绑定view的注解
 */
//保存的级别到运行时期
@Retention(RetentionPolicy.RUNTIME)
//目标->field 字段
@Target(ElementType.FIELD)
public @interface BindView {
    int viewId() default 0;//默认0
    boolean onClick() default false;//default表示默认
    boolean onLongClick() default false;//default表示默认
}

default表示默认值 ,也可以不编写默认值的。下面实现一个注解工具实现类:

/**
 * @Author lu an
 * Create Date is  2019/10/9
 * Des  注解工具类
 */
public class InjectUtils {
    public static void init(Activity ctx){
        //获取Class对象
        Class clazz = ctx.getClass();
        //获取字段变量
        Field[]fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //判断是否绑定了BindView
            if(field.isAnnotationPresent(BindView.class)){
                //获取到BindView对象
                BindView bindView = field.getAnnotation(BindView.class);
                //通过getAnnotation方法取出标记了注解的字段viewId
                int viewId = bindView.viewId();
                if(viewId>0){
                    field.setAccessible(true);
                    //获取到view
                    View childView = ctx.findViewById(viewId);
                    if (childView != null) {
                        //绑定的点击监听事件
                        if (bindView.onClick() && ctx instanceof View.OnClickListener) {
                            childView.setOnClickListener((View.OnClickListener) ctx);
                        }
                        if (bindView.onLongClick() && ctx instanceof View.OnLongClickListener) {
                            childView.setOnLongClickListener((View.OnLongClickListener) ctx);
                        }
                    }
                }
            }
        }
    }
}

通过反射方式,通过getAnnotation方法取出标记了注解的字段viewId,得到了viewId后,通过上下文findViewById找到对应的View控件,bindView.onClick() 对应的@BindView(viewId = R.id.btn_annotation,onClick = true)中的onClick值,ctx instanceof View.OnClickListener则表示Activity是否实现了点击接口.

下面就编写一个Activity类实现注解绑定view及其点击事件:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    //绑定view控件 和 绑定view的点击事件
    @BindView(viewId = R.id.btn_annotation,onClick = true)
    Button mBtnAnnotation;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注解初始化
        InjectUtils.init(this);
    }
    @Override
    public void onClick(View v) {
        Toast.makeText(this,"Binding View Success",Toast.LENGTH_SHORT).show();
    }
}

@BindView(viewId = R.id.btn_annotation,onClick = true)表示绑定view控件 和 绑定view的点击事件,如果只单单绑定view,如@BindView(viewId = R.id.btn_annotation)即可。

当你点击Button时就会弹出Binding View Success。

总结

上一篇 下一篇

猜你喜欢

热点阅读