【问题标题】:Is it safe to use Kotlin property access syntax to set a Java field使用 Kotlin 属性访问语法设置 Java 字段是否安全
【发布时间】:2018-07-24 12:52:54
【问题描述】:

这是一个假设性问题。 情况如下: 我正在从 Kotlin 文件中调用 Java 类的设置器来更改私有字段 x

的值
javaFoo.setX(420)

IDE 建议将其更改为

javaFoo.x = 420

正常工作。

现在假设 setter 内部有一些复杂的功能,后来 Java 类中的 x 字段更改为 public 而不是 private。不会出现编译错误,但 Kotlin 调用会更改 x 的值,从而跳过 setter 中发生的其他内容,并且可能会被忽视而导致逻辑错误。因此我想知道:使用 Kotlin 属性访问语法设置 java 字段是否安全?

【问题讨论】:

  • @Belzebub IDE 建议将其更改为...您能否提供一个示例让我重现它?
  • 我用的是android studio,只是创建一个带有私有字段和getter和setter的java类,然后从kotlin文件中调用setter
  • Java 库极不可能将一个字段从私有更改为公共,如果该字段也有一个 setter。此外,Kotlin 代码的行为只有在重新编译时才会改变。
  • 如果“setter 内部有一些复杂的功能”,那就更不可能了。

标签: java kotlin


【解决方案1】:

您对语言语义的分析是正确的。您描述的目标类的更改确实会更改 Kotlin 的属性访问语法的语义。然而,在回答您的问题时,这一事实并不是唯一要考虑的,它询问使用该语法是否安全

在讨论没有任何现实生活限制的假设场景时,几乎一切皆有可能,在这种观点下,没有任何语言结构是“安全的”。如果有一天,Kotlin 团队决定将x++ 的语义更改为“返回x 的平方,而不是更改x”怎么办?从理论上讲,这是可能的。有可能吗?

将相同的常识逻辑应用于您的问题,类的维护者决定打破迄今为止隐藏在具有自定义逻辑的设置器后面的字段的封装的情况极不可能。事实上,如果您对所有 Java 库项目进行历史分析,您可能不会发现这样的一个实例。


也就是说,您的假设场景可能会被视为对快捷语法的实际问题的干扰。使用它来调用具有自定义逻辑的 setter 可能会很尴尬和误导,因为它打破了我们的直觉。

在 Android 上,ImageView.get/setImageMatrix 就是一个这样的例子。你可以写

imageMatrix.rotate = 30

并期望这会产生影响,但实际上,您编写的代码已损坏。你其实应该写的

val tmpMatrix = Matrix()
tmpMatrix.set(imageMatrix)
tmpMatrix.rotate = 30
imageMatrix = tmpMatrix

根据我们的 Java 直觉,实际上是这个版本看起来很糟糕,浪费了一个看似毫无目的的对象分配。但是如果您阅读setImageMatrix 的合同,您会发现它不仅仅是将您的对象分配给一个字段,它实际上将转换应用于图像视图。类似地,getter 的约定不允许改变返回的对象。


我没有看到关于 Kotlin 的这一特性的太多争论,但我认为它是从 Java 迁移的人们的潜在错误来源。要走的路是重新训练你的直觉,让自己意识到 Kotlin 中的任何属性访问都可能意味着更多的东西。

【讨论】:

  • 这里对一般问题的分析很好,谢谢你的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-19
  • 2021-03-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多