在while表达式中不允许赋值?

27
在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)
}

根据这个帖子,这似乎是最好的解决方案:

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);
}

但是它真的是吗?
6个回答

40

不,我认为最好的方法是

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

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

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

太棒了!从这个答案中学到了很多!谢谢! - PedroD
啊,我建议了一次编辑,但我并不知道 it 语法糖的存在。太神奇了,还在不断学习中 :D - PedroD
在使用块中,r是什么? - sak
@sak BufferedReader - JB Nizet
在我的情况下,我必须将 foreach 更改为 forEach。不管怎样,非常感谢您的答案! - Takamitsu Mizutori

25

以下是Roman Elizarov提供的Kotlin风格的通用solution

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

这里的 breakNothing 类型,也有助于将 line 推断为非空字符串。


3
最佳简短答案 - zulkarnain shah

13

这是由stdlib提供支持并且可以安全地关闭读取器的最短解决方案:链接

reader.forEachLine {
    println(it)
}

4

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

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

generateSequence将逐个提取所有的值,直到遇到第一个null。如果你想保留最后一个值或将值求和到其他值,请使用reducefold(或任何其他合适的东西),替换.forEach

针对您具体的使用情况,您可以使用JB Nizet在他的回答中所示的内容或使用useLines

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

.forEachLine 可能是解决特定 readLine 问题的下一个最佳简写解决方案(已在此处回答),如果您知道您只想读取所有行,然后停止。


2
我发现这些天IntelliJ将你的Java代码转换成以下kotlin代码:
val br = BufferedReader(InputStreamReader(
        conn.inputStream))

var output: String
while (br.readLine().also { output = it } != null) {
    println(output)
}

这段内容仍然有些难以理解,但已经相当易读。它利用了also返回接收器实例的事实(在此处为br.readLine()的结果)。

-1

(这是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))) }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接