@AutoAnnotation 有什么用?怎么可能用? [英] What is @AutoAnnotation for? How could it be used?

查看:27
本文介绍了@AutoAnnotation 有什么用?怎么可能用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://dagger.dev/multibindings.html 中,我了解了 @AutoAnnotation.它引用了 https://github.com/google/auto/blob/master/value/src/main/java/com/google/auto/value/AutoAnnotation.java.

In https://dagger.dev/multibindings.html, I read about @AutoAnnotation. It has a reference to https://github.com/google/auto/blob/master/value/src/main/java/com/google/auto/value/AutoAnnotation.java.

它也在https://github.com/google/auto/blob/57dfad360306619a820e6aae4a14a1aa67c29299/value/userguide/howto.md#annotation

我读过它,无法理解它.

I read about it, can't get to understand it.

我设法使用我的 Android 代码访问它

I manage to access it from my Android code using

implementation 'com.google.auto.value:auto-value:1.5.2'
kapt 'com.google.auto.value:auto-value:1.5.2'

还有

android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true

但我不明白如何使用它.有什么好的使用教程吗?

But I don't understand how it could be used. Is there any good tutorial of using it?

推荐答案

AutoAnnotation 以与 JDK 相同的方式自动生成一个实现注解接口的类.

AutoAnnotation automatically generates a class that implements an annotation interface in the same way the JDK does.

当通过使用自定义注解作为键的 Dagger 使用 Multibindings 映射时,Dagger 会将实例 T 或 Provider Provider 安装到返回的映射中,使用注释实例本身作为键.为了更清楚地说明这一点:

When using a Multibindings map through Dagger that uses a custom annotation as its key, Dagger will install the instance T or Provider Provider<T> into the returned map, using the annotation instance itself as the key. To make this clearer:

@MapKey
@interface YourAnnotation {
  String foo();
}

@Provides @YourAnnotation(foo="bar") YourClass getYourClassForBar() { /* ... */ }

// Dagger will create a multibinding that would allow you to inject this:
@Inject Map<YourAnnotation, YourClass> map;

如果这里唯一重要的是 foo,您还可以使用 unwrapKeys 使映射由 String 而不是 YourAnnotation 键控,但假设您想要这个,因为您希望 YourAnnotation 将来具有多个值.但是 YourAnnotation 的实现是从哪里来的,你应该如何在地图上调用 get ?

If the only thing that matters here is foo, you could also use unwrapKeys to make the map keyed by String instead of YourAnnotation, but let's assume you want this because you want YourAnnotation to have multiple values in the future. But where do the implementations of YourAnnotation come from, and how are you supposed to call get on the map?

当您注释 Java 元素(通常是类、方法或字段)时,Java 将返回该类注释的特定实现.来自 Java 教程:

When you annotate a Java element (frequently a class, method, or field) Java will return a particular implementation of that class's annotation. From the Java tutorial:

@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
   String[] reviewers();
}

// [...]

@ClassPreamble (
   author = "John Doe",
   date = "3/17/2002",
   currentRevision = 6,
   lastModified = "4/12/2004",
   lastModifiedBy = "Jane Doe",
   // Note array notation
   reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {/* ... */}

在这种用法中,Generation3List 有一个 ClassPreamble 类型的注解.如果注释在运行时保留(即 ClassPreamble 本身是 @Retention(RUNTIME) 注释),您可以通过Generation3List.class.getAnnotations()Generation3List.class.getAnnotation(ClassPreamble.class)).(还有声明的对应物以不同的方式处理超类注释.)

In this usage, Generation3List has one Annotation of type ClassPreamble. If the annotation is retained at runtime (i.e. ClassPreamble itself is annotated with @Retention(RUNTIME)), you can get to it via Generation3List.class.getAnnotations() or Generation3List.class.getAnnotation(ClassPreamble.class). (There are also declared counterparts that handle superclass annotations differently.)

一旦您获得 ClassPreamble 的实例,您就可以使用 author()date() 等方法从类中检索数据.但是,ClassPreamble 表现为一个接口,并且该注解的实现在 VM 内部.这使得在运行时创建您自己的 ClassPreamble 的任意实例变得更加困难.

Once you get to an instance of ClassPreamble, you can use the methods like author() and date() to retrieve the data out of the class. However, ClassPreamble behaves as an interface, and the implementation of that annotation is internal to the VM. That makes it more difficult to create your own arbitrary instance of ClassPreamble at runtime.

因为 YourAnnotation 和 ClassPreamble 是接口,所以您可以创建一个实现.但是,与 VM 的实现相比,该实现不太可能具有 equalshashCode 的匹配实现,因为实现可能因 JRE 而异,在 Android 中也可能有所不同.然而,equalshashCode 的实现实际上是非常严格的在注释文档中:

Because YourAnnotation and ClassPreamble are interfaces, you could just create an implementation. However, that implementation is unlikely to have matching implementations of equals and hashCode compared to the VM's implementation, because the implementation may vary between JREs and may also vary in Android. However, the implementation of equals and hashCode is actually very closely prescribed in the docs for Annotation:

注解的哈希码是其成员(包括默认值的)的哈希码之和,定义如下:注解成员的哈希码是(成员名哈希码的127倍)由 String.hashCode() 计算) XOR 成员值的哈希码,定义如下 [...]

The hash code of an annotation is the sum of the hash codes of its members (including those with default values), as defined below: The hash code of an annotation member is (127 times the hash code of the member-name as computed by String.hashCode()) XOR the hash code of the member-value, as defined below [...]

如果指定的对象表示在逻辑上与此等效的注释,则返回 true.换句话说,如果指定的对象是与此实例具有相同注解类型的实例,则返回 true,其所有成员都等于此注解的对应成员,如下定义 [...]

Returns true if the specified object represents an annotation that is logically equivalent to this one. In other words, returns true if the specified object is an instance of the same annotation type as this instance, all of whose members are equal to the corresponding member of this annotation, as defined below [...]

手动实现这些规则是可能的,但很难做到,而且如果YourAnnotation或ClassPreamble的结构发生变化,也会带来负担.虽然 有反射解决此问题的方法,AutoAnnotation 会自动为符合要求的实现生成代码:

It is possible to manually implement these rules, but it would be difficult to do so, and it would also impose a burden if the structure of YourAnnotation or ClassPreamble were to change. Though there are reflective solutions to this problem, AutoAnnotation generates the code for a conforming implementation automatically:

public class YourAnnotations {
  @AutoAnnotation public static YourAnnotation yourAnnotation(String foo) {
    return new AutoAnnotation_YourAnnotations_yourAnnotation(foo);
  }
}

public class ClassPreambles {
  @AutoAnnotation public static ClassPreamble classPreamble(
      String author,
      String date,
      int currentRevision,
      String lastModified,
      String lastModifiedBy,
      String[] reviewers) {
    return new AutoAnnotation_ClassPreambles_classPreamble(
        author,
        date,
        currentRevision,
        lastModified,
        lastModifiedBy,
        reviewers);
  }
}

使用 AutoAnnotation 生成的实现,您可以在 Dagger Multibindings 生成的地图上调用 get(或提供您控制的测试实现),而无需处理特定于 Annotation 的 hashCodeXOR 或 equals 规则.这在 Dagger 和测试之外很有用,但由于 Dagger 在其地图中使用注释实例,因此您可能需要使用 AutoAnnotation 创建类似的实例.

With AutoAnnotation's generated implementation, you can call get on the map that Dagger Multibindings generates (or provide test implementations you control) without having to deal with Annotation-specific hashCode XORs or equals rules. This is useful beyond Dagger and tests, but because Dagger uses annotation instances in its maps, it makes sense that you might need to use AutoAnnotation to create similar instances.

这篇关于@AutoAnnotation 有什么用?怎么可能用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆