美文网首页
注解的理解

注解的理解

作者: Lucida_star | 来源:发表于2019-02-26 15:23 被阅读0次

    微信公众号:Lucidastar
    如有问题或建议,请公众号留言
    最近更新:2019-02-26

    注解的学习

    最近在学习dagger2,里头涉及到了很多的注解,感觉注解很简单,但是又说不上来,补充补充基础的知识吧。
    在平常的开发中,注解真的是无处不在,尤其在框架中,一个注解就可以做很多的事情,有时候就只记住了就应该这样写,这样配置,但是,脑袋中还是有很多的问号。所以让我们来了解一下。

    定义:
    注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。
    注解是众多引入到Java SE5中的重要的语言变化之一。它们可以提供用来完整地描述程序所需要的信息,而这些信息时无法用Java来表达的。因此,注解使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。注解可以用来生产描述符文件,甚至或者新的类定义,并且有助于减轻编写“样板”代码的负担。通过使用主角,我们可以将这些元数据保存在Java源代码中,并利用annotation API为自己的注解构造处理工具。

    优点:
    更加干净易读的代码以及编译期类型检查等。
    Java SE5中内置了三种,定义在java.lang中的注解:
    1、@Override,表示当前的方法定义将覆盖超类中的方法。如果不小心拼写错误,或者方法签名对不上被覆盖的方法,编译器就会错误提示。
    2、@Deprecated,使用了注解为它的元素,那么编译器会发出警告信息。
    3、@SuppressWarnings,关闭不当的编译器警告信息。

    元注解:
    指注解的注解,包含@Retention @Target @Document @Inherited四种

    @Retention(中文:保留):什么时候保留这些信息,它的参数一共就三个:

    ①RetentionPolicy.SOURCE – 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)//使用在源码上
    public @interface Override {
    }
    

    ②RetentionPolicy.CLASS – 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。

    @Documented
    @Retention(RetentionPolicy.CLASS)//class文件中
    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
    public @interface Nullable {
    }
    

    ③RetentionPolicy.RUNTIME– 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

    Java源文件(.java文件)---->.class文件---->内存中的字节码
    这是这三种的区别

    @Target(中文:目标,标记):注解用在什么地方,它的参数是一个数组:

    ①ElementType.TYPE: 用于描述类、接口或enum声明
    ②ElementType.FIELD: 用于描述实例变量
    ③ElementType.METHOD 方法声明
    ④ElementType.PARAMETER 参数声明
    ⑤ElementType.CONSTRUCTOR 构造声明
    ⑥ElementType.LOCAL_VARIABLE 局部变量声明
    ⑦ElementType.ANNOTATION_TYPE 另一个注释
    ⑧ElementType.PACKAGE 记录java文件的package信息

    @Document 将注解包含在Javadoc中

    @Inherited 允许子类继承父类中的注解

    注解的使用(使用Java编程思想中的例子来说明)
    定义一个注解:

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface UseCase {
        public int id();
        public String description () default "no description";
    }
    

    使用注解:

    public class PasswordUtils {
        @UseCase(id = 47, description = "Passwords must contain at least one numeric")
        public boolean validatePassword(String password) {
            return (password.matches("\\w*\\d\\w*"));
        }
        @UseCase(id = 48)
        public String encryptPassword(String password) {
            return new StringBuilder(password).reverse().toString();
        }
        @UseCase(id = 48,description = "New passwords can't equal previously used ones")
        public boolean checkForNewPassword(List<String> prevPasswords ,String password){
            return !prevPasswords.contains(password);
        }
    }
    

    对注解的处理:

    public static void main(String[] args) {
        List<Integer> useCases = new ArrayList<Integer>();
        Collections.addAll(useCases, 47, 48, 49, 50);
        trackUseCases(useCases, PasswordUtils.class);
    
        Integer max = Collections.max(useCases);
        System.out.println(max);
    }
    
    public static void trackUseCases(List<Integer> useCases, Class<?> cl) {
        for (Method m : cl.getDeclaredMethods()) {
            UseCase uc = m.getAnnotation(UseCase.class);
            if (uc != null) {
                System.out.println("Found Use Case:" + uc.id() + " "
                        + uc.description());
                useCases.remove(new Integer(uc.id()));
            }
        }
        for (int i : useCases) {
            System.out.println("Warning: Missing use case-" + i);
        }
    }
    

    注解这算就学完了,明白了吗?说实在,我也不明白。我们来推测一下butterknife这个框架,应用在Android绑定view中,我们来看一下他是怎么使用的?


    绑定

    现在mTvTest就已经实例化了,为我们省略了findViewById(),我们看一下BindView的注解。

    @Retention(RUNTIME) @Target(FIELD)
    public @interface BindView {
      /** View ID to which the field will be bound. */
      @IdRes int value();
    }
    

    保留方式是使用的内存中的字节码(RUNTIME) target使用的是实例变量,然后我们把注解声明在了变量(控件变量)上,然后使用ButterKnife.bind(this);就实例化了控件,我们来看一下它是如何处理的

    Class<?> targetClass = target.getClass();
    if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());
    Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);//获取类中的公共方法
    if (constructor == null) {
      return Unbinder.EMPTY;
    }
    //noinspection TryWithIdenticalCatches Resolves to API 19+ only type.
    try {
      return constructor.newInstance(target, source);
    }
    
    @Nullable 
    @CheckResult 
    @UiThread
    private static Constructor<? extends Unbinder> findBindingConstructorForClass(Class<?> cls) {
      Constructor<? extends Unbinder> bindingCtor = BINDINGS.get(cls);
      if (bindingCtor != null || BINDINGS.containsKey(cls)) {
        if (debug) Log.d(TAG, "HIT: Cached in binding map.");
        return bindingCtor;
      }
      String clsName = cls.getName();
      if (clsName.startsWith("android.") || clsName.startsWith("java.")
          || clsName.startsWith("androidx.")) {
        if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");
        return null;
      }
      try {
        Class<?> bindingClass = cls.getClassLoader().loadClass(clsName + "_ViewBinding");
        //noinspection unchecked
        bindingCtor = (Constructor<? extends Unbinder>) bindingClass.getConstructor(cls, View.class);
        if (debug) Log.d(TAG, "HIT: Loaded binding class and constructor.");
      } catch (ClassNotFoundException e) {
        if (debug) Log.d(TAG, "Not found. Trying superclass " + cls.getSuperclass().getName());
        bindingCtor = findBindingConstructorForClass(cls.getSuperclass());
      } catch (NoSuchMethodException e) {
        throw new RuntimeException("Unable to find binding constructor for " + clsName, e);
      }
      BINDINGS.put(cls, bindingCtor);
      return bindingCtor;
    }
    

    主要能看懂注解代码就可以,注解一般在设计框架时用的比较多一些。

    我的公众号:Lucidastar

    image

    相关文章

      网友评论

          本文标题:注解的理解

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