自定义注解(Annotation)基本使用

从 jdk5开始,Java增加了对元数据的支持,也就是Annotation,Annotation其实就是对代码的一种特殊标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理。当然刚刚说了,Annotation只是一种标记,所以要是在代码里面不用这些标记也是能完成相应的工作的,只是有时候用注解能简化很多代码,看起来非常的简洁。

基本的Annotation

@Override——限定重写父类方法
  ● @Deprecated——标示已过时
  ● @SuppressWarning——抑制编译器警告
  ● @SafeVarargs——这货与Java7里面的堆污染有关

JDK的元Annotation,元注解

JDK除了提供上述的几种基本的Annotation外,还提供了几种Annotation,用于修饰其他的Annotation定义

  1. @Retention 这个是决定你Annotation存活的时间的,它包含一个RetationPolicy的value成员变量,用于指定它所修饰的Annotation保留时间,一般有:

      ○ Retationpolicy.CLASS:编译器将把Annotation记录在Class文件中,不过当java程序执行的时候,JVM将抛弃它。


      ○ Retationpolicy.SOURCE : Annotation只保留在原代码中,当编译器编译的时候就会抛弃它。


      ○ Retationpolicy.RUNTIME : 在Retationpolicy.CLASS的基础上,JVM执行的时候也不会抛弃它,所以我们一般在程序中可以通过反射来获得这个注解,然后进行处理。



  2. @Target 这个注解一般用来指定被修饰的Annotation修饰哪些元素,这个注解也包含一个value变量:

      ○ ElementType.ANNOTATION_TYPE : 指定该Annotation只能修饰Annotation。


      ○ ElementType.CONSTRUCTOR: 指定只能修饰构造器。


      ○ ElementType.FIELD: 指定只能成员变量。


      ○ ElementType.LOCAL_VARIABLE: 指定只能修饰局部变量。


      ○ ElementType.METHOD: 指定只能修饰方法。


      ○ ElementType.PACKAGE: 指定只能修饰包定义。


      ○ ElementType.PARAMETER: 指定只能修饰参数。


      ○ ElementType.TYPE: 指定可以修饰类,接口,枚举定义。



  3. @Document  这个注解修饰的Annotation类可以被javadoc工具提取成文档


  4. @Inherited  被他修饰的Annotation具有继承性

例子

自定义注解MyAnnotation

@Retention(RetentionPolicy.RUNTIME)//运行时
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})//范围类接口,方法,变量
//@Deprecated //标记过时
@Inherited //注解可被继承
public @interface MyAnnotation {
    String value();//只有一个方法是用value()
}

自定义注解MyAnnotation2

@Retention(RetentionPolicy.RUNTIME)//运行时
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})//范围类接口,方法,变量
//@Deprecated //标记过时
@Inherited //注解可被继承
public @interface MyAnnotation2 {
    String name2();
    int age2();
}

在实例中使用

@MyAnnotation("类注解")
public class User {

    @Deprecated
    private String userName;

    @Deprecated
    public void fun() {
        //已过时
    }

    @MyAnnotation("fun2方法注解")
    public void fun2(){

    }
    @MyAnnotation2(name2 = "Coco",age2 = 22)
    public void fun3(){

    }


}

测试

public static void main(String[] args) {
        try {
            //得到user字节码
            Class c = Class.forName("com.bwie.reflectdemo1.User");
            //通过反射得到fun3
            Method method = c.getMethod("fun3", null);
            //得到fun3上的注解
            MyAnnotation2 myAnnotation2 = method.getAnnotation(MyAnnotation2.class);
            //打印结果
            System.out.println(myAnnotation2.name2()+"--fun3上的注解(多值)--"+myAnnotation2);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

打印结果

Coco--fun3上的注解(多值)--@com.bwie.reflectdemo1.annotation.MyAnnotation2(name2=Coco, age2=22)

例子2

* 绑定控件,绑定布局,绑定点击事件*
MainActivity

/**
 * 1.自定义类注解和成员变量注解
 * 2.绑定主布局
 * 3。绑定控件
 */
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv)
    TextView textView;
    /*@BindView(R.id.btn)
    Button button;*/
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        InjectUtils.inject(this);
        System.out.println(textView);
        textView.setText("++++++++++++++++");

    }
    @MClick({R.id.btn})
    public void click(View view) {
        Toast.makeText(this, "点击了", Toast.LENGTH_SHORT).show();
    }
}

绑定控件

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface BindView {
    int value();
}

绑定布局

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
public @interface ContentView {
    int value();
}

绑定点击事件

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

工具类(通过反射操作相关逻辑)

public class InjectUtils {
    /**
     * 注入activity,通过反射运行相关逻辑
     */
    public static void inject(Activity activity) {
        injectContentView(activity);
        injectBindView(activity);
        injectBindOnClick(activity);
    }

    //绑定点击事件
    private static void injectBindOnClick(final Activity activity) {
        Class c = activity.getClass();
        Method[] methods = c.getDeclaredMethods();
        for (final Method method : methods) {
            method.setAccessible(true);
            MClick annotation = method.getAnnotation(MClick.class);
            if (annotation != null) {
                int[] value = annotation.value();
                for (int i : value) {
                    int id = i;
                    final View btn = activity.findViewById(id);
                    btn.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            try {
                                method.invoke(activity,btn);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                            Log.d(TAG, "onClick: "+1);
                        }
                    });
                }
            }

        }
    }

    //注入contentview
    private static void injectBindView(Activity activity) {
        //得到activity字节码
        Class clazz = activity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        if (fields != null && fields.length > 0) {
            for (Field field : fields) {
                //设置权限
                field.setAccessible(true);
                //得到成员变量的注解
                BindView bindView = field.getAnnotation(BindView.class);
                if (bindView != null) {
                    //注释的值
                    int value = bindView.value();
                    //得到每个id的view
                    View view = activity.findViewById(value);
                    try {
                        field.set(activity,view);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }

                }
            }
        }

    }

    /**
     * 绑定contentview,实现其逻辑
     */
    private static void injectContentView(Activity activity) {

        //得到Activity字节码
        Class clazz = activity.getClass();
        //得到类上面的注解
        ContentView contentView = (ContentView) clazz.getAnnotation(ContentView.class);
        if (contentView!=null){
            int layoutId = contentView.value();

            try {
                Method method = clazz.getMethod("setContentView", int.class);
                method.invoke(activity,layoutId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }





}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值