android框架设计基础--java注解全面解析

196 阅读5分钟
原文链接: www.jianshu.com

最近在看第三方的优秀开源库源码,发现好多地方都用到了注解,这里,觉得有必要对java注解做个总结,方便以后自己查阅及大家学习了解.

本文主要用以下三方面讲解:

  • 概念,什么是java注解;
  • java自带的注解有哪些;
  • 自定义注解,及解析,如何使用;

概念

Java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法。 Java1.5引入了注解,当前许多java框架中大量使用注解,如Hibernate、Jersey、Spring。注解作为程序的元数据嵌入到程序当中。注解可以被一些解析工具或者是编译工具进行解析。我们也可以声明注解在编译过程或执行时产生作用。

java自带的注解

java自带的注解其实不多,有三种标准注解和四种元注解,下面简单介绍下:

三种标准注解:
  • @Override
    表示覆盖或重写父类的方法;当我们想要复写父类中的方法时,我们需要使用该注解去告知编译器我们想要复写这个方法。这样一来当父类中的方法移除或者发生更改时编译器将提示错误信息。

  • @Deprecated
    表示该方法已经过时了。(当方法或是类上面有@Deprecated注解时,说明该方法或是类都已经过期不能再用,但不影响以前项目使用,提醒你新替代待的方法或是类。如果程序员不小心使用了它的元素,那么编译器会发出警告信息)

  • @SuppressWarnings
    表示忽略指定警告,比如@Suppvisewarnings("Deprecation")

这三个注解应该大家都明白,在我们日常的代码很常见,这里就不多说了。

元注解:

元注解,很重要,后面讲的自定义注解,都会用到,所以后面的好好了解下:

  • @Target 是注解的作用域
    表示该注解可以用于一个类中的那些属性及方法上,如果作用域类型有多个用英文逗号分隔,该元注解的取值可以TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。下面分别对取值进行讲解:
    • @Target(ElementType.ANNOTATION_TYPE) :
      注解
    • @Target(ElementType.CONSTRUCTOR):
      构造方法声明
    • @Target(ElementType.FIELD)
      字段声明
    • @Target(ElementType.LOCAL_VARIABLE)
      局部变量声明
    • @Target(ElementType.METHOD)
      方法声明
    • @Target(ElementType.PACKAGE)
      包声明
    • @Target(ElementType.PARAMETER)
      参数声明
    • @Target(ElementType.TYPE):
      类,接口(包括注解),枚举
    • @Target(ElementType.TYPE_PARAMETER):
      类型
    • @Target(ElementType.TYPE_USE):
      类型

这三个类型ElementType.TYPE_USE,ElementType.TYPE_PARAMETER是Java8新增的。

  • @Retention
    表示该注解的生命周期
    • @Retention(RetentionPolicy.CLASS)
      注解被编译器保存在字节码文件中,在运行时丢弃,默认的保留行为
    • @Retention(RetentionPolicy.RUNTIME)
      被虚拟机保存,可用反射机制读取
    • @Retention(RetentionPolicy.SOURCE)
      注解保留在源码阶段,被编译器丢弃
  • @Inherited
    此注解是标识性的元注解,表示当前注解可以由子注解来继承
  • @Documented
    表示生成javadoc的时候会包含注解

自定义注解

自定义注解在框架设计上得比较多,因为使用注解可以让编程更加简洁,代码更加清晰;哈哈,还有一条就是装逼,一看就高大上,接下来看如何自定义注解,及如何使用自定义注解;

如何自定义注解?
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Persion {
    String name();
    String sex();
    int age() default 20;
}

1.上面的代码是一个完整的自定义注解,创建自定义注解和创建一个接口相似,但是注解的interface关键字需要以@符号开头;

2.@Target表示此注解的作用域,作用于方法,类,有多个作用域时用{}括起来,之间用,间隔开;

3.@Retention 表示该注解的生命周期,此例子说明该注解的生命周期是被虚拟机保存,可用反射机制读取

4.成员是以无参无异常方式声明,可以用default为成员指定一个默认值,成员类型是受限的,合法的类型包括基本类型、String、Enums、Annotation,Class;还有一个重要的要注意,如果注解只有一个成员时,则成员名必须取名为value();在使用时可以忽略成员名和赋值号(=)

5.注解类可以没有成员,没有成员的注解称为标识注解;

如何使用注解
@Persion(name = "Xiaomi",sex = "man",age = 15)
public class Xiaomi {
    String fatherName;
}

看上面代码,看是不是使用很简单,只要在类的上面加上@注解名(成员1=成员1值,成员2=成员2值,...)就行;

解析注解
try {
            Class c=Class.forName("com.sz.annotationdemo.Xiaomi");
            if (c==null){
                Log.i("ms","Persion class不存在");
            }else{
                boolean isExist=c.isAnnotationPresent(Persion.class);
                if (isExist){
                    Persion persion= (Persion) c.getAnnotation(Persion.class);
                   Log.i("ms",persion.name()+",,,"+persion.sex()+",,,"+persion.age());
                }else {
                    Log.i("ms","Persion注解不存在");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

通过反射获取类、函数或成员上运行时注解信息,从而实现动态控制程序运行的逻辑。
使用forName()方法加载类,并使用getAnnotation(Persion.class)检查该类是否带有@Persion注解。
注解的继承只能作用在类上,方法上的注解不会被继承,Interface中的所有注解不会被继承。
运行后得到结束:

01-30 17:52:53.638 11283-11283/? I/ms: Xiaomi,,,man,,,15

哈哈,是不是通过自定义注解,注入,然后就可以获取注入的数据,到这里应该明白了吧.以后就可以实际项目解决注解问题了.

本人做android开发多年,以后会陆续更新关于android高级UI,NDK开发,性能优化等文章,更多请关注我的微信公众号:谢谢!
android的那点事.jpg