Как преобразовать выражение назначения Java в Kotlin
Что-то в java как
int a = 1, b = 2, c = 1;
if ((a = b) !=c){
System.out.print(true);
}
теперь он должен быть преобразован в kotlin как
var a:Int? = 1
var b:Int? = 2
var c:Int? = 1
if ( (a = b) != c)
print(true)
но это не правильно.
Вот ошибка, которую я получаю:
in " (a=b)" Error:(99, 9) Kotlin: Assignments are not expressions, and only expressions are allowed in this context
На самом деле приведенный выше код является лишь примером для выяснения проблемы. Вот мой оригинальный код:
fun readFile(path: String): Unit {
var input: InputStream = FileInputStream(path)
var string: String = ""
var tmp: Int = -1
var bytes: ByteArray = ByteArray(1024)
while((tmp=input.read(bytes))!=-1) { }
}
Ответы
Ответ 1
Как правильно указано @AndroidEx, присваивания не являются выражениями в Kotlin, в отличие от Java. Причина в том, что выражения с побочными эффектами обычно обескуражены. См. это обсуждение по аналогичной теме.
Одно из решений состоит в том, чтобы разделить выражение и переместить назначение из блока условий:
a = b
if (a != c) { ... }
Другим является использование функций из stdlib, таких как let
, который выполняет lambda с приемником в качестве параметра и возвращает результат лямбда. apply
и run
имеют схожую семантику.
if (b.let { a = it; it != c }) { ... }
if (run { a = b; b != c }) { ... }
Благодаря inlining, это будет так же эффективно, как простой код, взятый из лямбда.
Ваш пример с InputStream
будет выглядеть как
while (input.read(bytes).let { tmp = it; it != -1 }) { ... }
Также рассмотрим функцию readBytes
для чтения ByteArray
с InputStream
.
Ответ 2
Назначения не являются выражениями в Kotlin, поэтому вам нужно сделать это снаружи:
var a: Int? = 1
var b: Int? = 2
var c: Int? = 1
a = b
if (a != c)
print(true)
Для вашего другого примера с InputStream
вы можете сделать:
fun readFile(path: String) {
val input: InputStream = FileInputStream(path)
input.reader().forEachLine {
print(it)
}
}
Ответ 3
Как почти все здесь отметили, присваивания не являются выражениями в Котлине. Однако мы можем принудить назначение к выражению, используя литерал функции:
val reader = Files.newBufferedReader(path)
var line: String? = null
while ({ line = reader.readLine(); line }() != null) {
println(line);
}
Ответ 4
Java: (a = b) != c
Kotlin: b.also { a = it } != c
Вокруг ОП вопрос:
В отличие от принятого ответа, я рекомендую использовать Kotlin also
функцию вместо let
:
while (input.read(bytes).also { tmp = it } != -1) { ...
Поскольку T.also
возвращает T
(it
) сам, вы можете сравнить его с -1
. Это больше похоже на назначение Java как утверждение.
Подробности смотрите в разделе "Возвращение против другого типа" в этом полезном блоге.
Ответ 5
Я думаю, это может вам помочь:
input.buffered(1024).reader().forEachLine {
fos.bufferedWriter().write(it)
}
Ответ 6
простой способ в котлине
if (kotlin.run{ a=b; a != c}){ ... }