Как преобразовать выражение назначения 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}){ ... }