模糊的JvmSynthetic setter方法调用

huangapple go评论117阅读模式
英文:

Ambiguous method call with JvmSynthetic setter

问题

class PersonBuilder {
@set:JvmSynthetic // 隐藏一个无返回值的 setter 方法,对 Java 客户端不可见
var age: Int? = null

@set:JvmSynthetic
var name: String? = null

fun setAge(age: Int?) = apply { this.age = age }

fun setName(name: String?) = apply { this.name = name }

fun build() = Person(age!!, name!!)

}


在 Java 一侧这样调用它:

```java
new PersonBuilder()
        .setAge(22)  // <- "error"
        .setName("Peter")
        .build();

它能够编译和运行,但是 Android Studio 显示错误 "模糊的方法调用。setAge (Integer) 在 PersonBuilder 中匹配",并且在这个 "错误" 后不提供任何自动建议和代码格式化。

英文:

I have a class with @JvmSynthetic setters in order to provide only fluent builder-like setters for Java clients:

class PersonBuilder {
    @set:JvmSynthetic    // hide a void setter from Java
    var age: Int? = null

    @set:JvmSynthetic
    var name: String? = null

    fun setAge(age: Int?) = apply { this.age = age }

    fun setName(name: String?) = apply { this.name = name }

    fun build() = Person(age!!, name!!)
}

And call it like this on the Java side:

new PersonBuilder()
        .setAge(22)  // &lt;- &quot;error&quot;
        .setName(&quot;Peter&quot;)
        .build();

It does compile & run, but Android Studio shows the error "Ambiguous method call. Both setAge (Integer) in PersonBuilder and setAge (Integer) in PersonBuilder match" and doesn't provide any auto-suggestions and code formating after this "error".

答案1

得分: 1

我认为没有必要使用@set:JvmSynthetic标记,只需更改变量的可见性就可以了。尝试这样做:

class PersonBuilder {
    private var age: Int? = null
    private var name: String? = null

    fun setAge(age: Int) = apply { this.age = age }

    fun setName(name: String) = apply { this.name = name }

    fun build() = Person(age!!, name!!) //注意潜在的空指针异常!
}

不管怎样,要小心build函数。不能保证setAgesetName函数会在它之前被调用,所以可能会导致空指针异常。

更新

另一种通过保留@JvmSynthetic来解决这个问题的方法是添加@JvmField标记。更多信息请参阅这篇文章

英文:

I believe there is no need to use the @set:JvmSynthetic notation, just changing the visibility of variables should do the trick. Try this:

class PersonBuilder {
    private var age: Int? = null
    private var name: String? = null

    fun setAge(age: Int) = apply { this.age = age }

    fun setName(name: String) = apply { this.name = name }

    fun build() = Person(age!!, name!!) //be careful!
}

Anyway, be careful with the build function. There are no guarantees that the functions setAge and setName will be called before it, so you can get a NullPointerException

Update

Another way to solve this problem by keeping @JvmSynthetic is to add the @JvmField notation as well. See this article for more information.

huangapple
  • 本文由 发表于 2020年8月6日 20:39:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63283828.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定