如何使用Kotlin紧凑构造函数语法使用Room库的@Ignore注释?

时间:2018-02-07 21:48:04

标签: android kotlin android-room

我试图同时使用android Room库和Kotlin的紧凑语法来指定具有默认参数值的构造函数。像这样:

@Entity
class MyEntity(var myString:String = "non-trivial string") {

    @PrimaryKey(autoGenerate = true)
    var myIndex:Int = 0
}

但是我收到了这条警告信息:

  

有多个好的构造函数,Room会选择no-arg构造函数。您可以使用@Ignore注释来消除不需要的构造函数。

语法在哪里允许使用这种紧凑的Kotlin构造函数来编写Room的@Ignore注释?

我知道我可以做这样的事情来消除那条警告信息,但它更加冗长。它还使构造函数arg默认值看起来多余/无用:

@Entity
class MyEntity() {

    @Ignore
    constructor(myString:String = "non-trivial string") : this() {
        this.myString = myString
    }

    @PrimaryKey(autoGenerate = true)
    var myIndex:Int = 0

    var myString:String? = null
}

我如何宣布一个房间实体,但仍然利用Kotlin的简洁?

谢天谢地。

3 个答案:

答案 0 :(得分:3)

如果要向主构造函数添加注释,则必须添加constructor关键字:

class MyEntity @Ignore constructor(var myString:String = "non-trivial string")

documentation州:

  

如果主构造函数没有任何注释或可见性修饰符,则可以省略constructor关键字。

答案 1 :(得分:1)

这个怎么样:

@Entity
class MyEntity(
    var myString: String = "non-trivial string",

    @PrimaryKey(autoGenerate = true)
    var myIndex: Int = 0
)

答案 2 :(得分:1)

我们来看看这段代码:

class MyEntity(var myString: String = "default value")

如果你反编译它,你得到的东西相当于下面的Java代码(省略了getter / setter):

public final class MyEntity {
  @NotNull
  private String myString;

  // getters and setters omitted

  public MyEntity(@NotNull String myString) {
     Intrinsics.checkParameterIsNotNull(myString, "myString");
     super();
     this.myString = myString;
  }

  // $FF: synthetic method
  public MyEntity(String var1, int var2, DefaultConstructorMarker var3) {
     if ((var2 & 1) != 0) {
        var1 = "default value";
     }

     this(var1);
  }

  public MyEntity() {
     this((String)null, 1, (DefaultConstructorMarker)null);
  }
}

因此,您将获得2个构造函数+ 1个合成构造函数。这并不疯狂,因为它必须支持带有字符串参数的构造函数和没有任何参数的构造函数(并且记住MyEntity可以从Java代码实例化,因此Kotlin编译器必须创建两个构造函数。)

相反,如果您编写此代码:

class MyEntity(myString: String?) {

    val myString: String

    init {
        if (myString == null) {
            this.myString = ""
        } else {
            this.myString = myString
        }
    }

}

您获得的字节码等同于以下Java代码(省略了getter / setter):

public final class MyEntity {
  @NotNull
  private String myString;

  // getter and setter omitted

  public MyEntity(@Nullable String myString) {
     if (myString == null) {
        this.myString = "default value";
     } else {
        this.myString = myString;
     }

  }
}

使用第二段Kotlin代码,您应该能够删除警告并保持myString属性不可为空,即使它与Kotlin代码的第一个片段不完全相同,因为您始终需要在构造函数中提供参数。