gson 使用@field:SerializedName注解而不是@SerializedName的目的是什么?

ffscu2ro  于 2022-11-06  发布在  其他
关注(0)|答案(3)|浏览(245)

通常,我使用@SerializedName注解来MapJSON字段。但是,在Google Architecture Component示例项目中,我看到他们使用@field:SerializedName注解,但我找不到任何地方来阅读使用@field注解的目的。
我是新来的Kotlin,可以有人解释或分享参考链接阅读?谢谢。

@Entity(
    indices = [
        Index("id"),
        Index("owner_login")],
    primaryKeys = ["name", "owner_login"]
)
data class Repo(
    val id: Int,
    @field:SerializedName("name")
    val name: String,
    @field:SerializedName("full_name")
    val fullName: String,
    @field:SerializedName("description")
    val description: String?,
    @field:SerializedName("owner")
    @field:Embedded(prefix = "owner_")
    val owner: Owner,
    @field:SerializedName("stargazers_count")
    val stars: Int
) {...
fbcarpbf

fbcarpbf1#

虽然在这种情况下使用@field:SerializedName(...)并不 * 不正确 *,但 * 是 * 不必要的:无论是否添加field:,都将生成相同的字节码,因为无论哪种方式,只有private backing字段将获得注解。我从未见过一个实际的项目更喜欢@field:SerializedName而不是@SerializedName,我认为Google示例的使用对初学者来说是不必要的混淆。您可以随意忽略它。

btxsgosb

btxsgosb2#

这可能有助于:从Kotlin文档
当你为一个属性或主构造函数参数添加注解时,有多个Java元素是从相应的Kotlin元素生成的,因此在生成的Java字节码中有多个可能的注解位置。要指定如何准确地生成注解,请使用以下语法:

class Example(@field:Ann val foo,    // annotate Java field
              @get:Ann val bar,      // annotate Java getter
              @param:Ann val quux)   // annotate Java constructor parameter
bogh5gae

bogh5gae3#

TL;DR:field:部分被称为“use-site target”,它清楚地表明注解应用于Kotlin属性的支持字段。在这种情况下,它并不是严格必要的,尽管它可以使代码更具可读性。

说明

为了简化,假设您有:

data class Repo(
    @field:SerializedName("name")
    var name: String
)

这段代码通过主构造函数声明了一个data class沿着它的properties。Kotlin属性由属性本身、一个getter和一个setter(如果是可变的)组成。这对我们来说意味着什么?这意味着仅仅一个属性就有很多东西要做。在这里,name的注解可以1应用于以下任何一个:

  • 建构函式参数。
  • Kotlin地产本身。
  • 吸气剂。
  • 二传手。
  • setter的参数。
  • 属性的支援字段。

通过使用field:(称为“use-site target”),您可以清楚地表明注解应用于属性的 backing字段
但是,我应该注意到,在这种情况下使用field:仍然会导致注解被应用到支持字段。(构造函数参数),property(Koltin属性),以及field@SerializedName 2注解不适用于param s。由于它是Java注解,因此不可能适用于property s。但该注解适用于field s,这就是它的结局。
1.
没有任何真正的歧义,因为规则定义得很清楚(请参阅下面的文档)。但这是关于编译器的。对于人类来说,乍一看代码可能不清楚,这才是真正重要的。use-site目标可能不是严格必要的,但它使代码更可读(至少在我看来)。

2.* 您已将此问题标记为gson,因此我假设注解来自此处。*

文件

下面是Kotlin文档对此进行了讨论:

注解使用部位目标

当你为一个属性或主构造函数参数添加注解时,有多个Java元素是从相应的Kotlin元素生成的,因此在生成的Java字节码中有多个可能的注解位置。要指定如何准确地生成注解,请使用以下语法:

class Example(@field:Ann val foo,    // annotate Java field
              @get:Ann val bar,      // annotate Java getter
              @param:Ann val quux)   // annotate Java constructor parameter

同样的语法也可以用来注解整个文件。要做到这一点,请在文件的顶层放置一个带有目标file的注解,如果该文件在默认包中,则在package指令之前或所有导入之前:

@file:JvmName("Foo")
package org.jetbrains.demo

如果您有多个具有相同目标的注解,则可以通过在目标后面添加括号并将所有注解放在括号内来避免重复目标:

class Example {
     @set:[Inject VisibleForTesting]
     var collaborator: Collaborator
}

受支持的使用站点目标的完整列表为:

  • file ;
  • property(Java看不到带有此目标的注解);
  • field ;
  • get(属性获取器);
  • set(属性设置器);
  • receiver(扩展函数或属性的接收器参数);
  • param(构造函数参数);
  • setparam(属性设置器参数);
  • delegate(存储委托属性的委托示例的字段)。

要为扩展函数的receiver参数添加注解,请使用以下语法:

fun @receiver:Fancy String.myExtension() { ... }

如果未指定use-site目标,则会根据所使用注解的@Target注解来选择目标。如果有多个适用的目标,则会使用以下列表中的第一个适用目标:

  • param ;
  • property ;
  • field .

相关问题