【问题标题】:Assignment not allowed in while expression?while 表达式中不允许赋值?
【发布时间】:2017-05-23 02:26:02
【问题描述】:

在 Java 中,我们通常可以在 while 条件内执行赋值。然而,Kotlin 对此抱怨不已。所以下面的代码无法编译:

val br = BufferedReader(InputStreamReader(
        conn.inputStream))

var output: String
println("Output from Server .... \n")
while ((output = br.readLine()) != null) { // <--- error here: Assignments are not expressions, and only expressions are allowed in this context
    println(output)
}

根据另一个thread,这似乎是最好的解决方案:

val reader = BufferedReader(reader)
var line: String? = null;
while ({ line = reader.readLine(); line }() != null) { // <--- The IDE asks me to replace this line for while(true), what the...?
  System.out.println(line);
}

是吗?

【问题讨论】:

    标签: kotlin kotlin-interop


    【解决方案1】:

    我发现这些天 IntelliJ 将你的 Java 代码转换为以下 kotlin 代码:

    val br = BufferedReader(InputStreamReader(
            conn.inputStream))
    
    var output: String
    while (br.readLine().also { output = it } != null) {
        println(output)
    }
    

    这仍然令人困惑,但它的可读性很强。它使用also 返回接收器实例的事实(这里是br.readLine() 的结果)。

    【讨论】:

      【解决方案2】:

      这是一个简短的 Kotlin 风格的将军 solution,作者 Roman Elizarov:

      while (true) {
          val line = reader.readLine() ?: break
          println(line);
      }
      

      这里break 具有Nothing 类型,这也有助于将line 的类型推断提升为不可为空的字符串。

      【讨论】:

      • 最佳简短答案
      【解决方案3】:

      不,IMO 最好的方法是

      val reader = BufferedReader(reader)
      reader.lineSequence().forEach {
          println(it)
      }
      

      如果您想确保阅读器正确关闭(就像您在 Java 中使用 try-with-resources 语句一样),您可以使用

      BufferedReader(reader).use { r ->
          r.lineSequence().forEach {
              println(it)
          }
      }
      

      【讨论】:

      • 太棒了!通过这个答案学到了很多东西!谢谢!
      • 啊,我建议编辑,我对it 语法糖知之甚少。太棒了,还在学习:D
      • use块中的r是什么?
      • @sak The BufferedReader
      • 就我而言,我必须将foreach 更改为forEach。无论如何,非常感谢您的回答!
      【解决方案4】:

      如果您只想替换 while ((x = y.someFunction()) != null),您可以使用以下代码:

      generateSequence { y.someFunction() }
                .forEach { x -> /* what you did in your while */ }
      

      generateSequence 将逐个提取所有值,直到达到第一个 null。如果您想保留最后一个值或将这些值总结为其他值,您可以将 .forEach 替换为 reducefold(或其他任何似乎合适的东西;-))。

      但是,对于您的特定用例,您可以只使用JB Nizet in his answer 显示的内容或使用useLines

      reader.useLines {
        it.forEach(::println)
      }
      

      .forEachLine 可能是针对特定readLine-问题(已回答here)的下一个最佳速记解决方案,如果您知道自己只想阅读所有行然后停下来。

      【讨论】:

        【解决方案5】:

        (此示例用于 while 循环)希望此示例对您有所帮助..

        改变

        while ((c = is.read(buffer)) > 0) { sb.append(String(buffer, 0, c, Charset.forName(UTF8))) }

        while ({c = is.read(buffer);c}() > 0) { sb.append(String(buffer, 0, c, Charset.forName(UTF8))) }

        【讨论】:

          【解决方案6】:

          这是 stdlib 的最短解决方案powered,它也可以安全地关闭阅读器:

          reader.forEachLine {
              println(it)
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-10-09
            • 1970-01-01
            • 1970-01-01
            • 2021-11-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-24
            相关资源
            最近更新 更多