'if' must have both main and 'else' branches if used as an expression

Viewed 8885

I have the code below working before, now compiler halts and marks both if statements and says:

'if' must have both main and 'else' branches if used as an expression

But as you see this is not an expression, but just a simple equality statement and a conditional statement next to it.

try {
    val json_string = responseBody!!.string()
    val jsonObject = JSONObject(json_string)
    if (jsonObject.has("version")) {

        val remoteVersion = jsonObject.getInt("version")
        if (remoteVersion > BuildConfig.VERSION_CODE) {
            handler.post {
                showInstallNewVersionDialog()
            }
        }
    }
} catch (e: Exception) {
    e.message?.let { Log.e(Constants.TAG, e.message!!) }

}

The funny part is if I added empty else tags, it will run but will warn to remove empty else statements:

if (jsonObject.has("version")) {

    val remoteVersion = jsonObject.getInt("version")
    if (remoteVersion > BuildConfig.VERSION_CODE) {
        handler.post {
            showInstallNewVersionDialog()
        }
    } else {}
} else {}
3 Answers

If IDE tells you that 'if' must have both main and 'else' branches if used as an expression then it is so. Most likely this try-catch construction is defined as a custom getter of a variable or as single-expression function.

An example:

val aVariable =
    try {
        if (System.currentTimeMillis() == 0L) {
            println("It is 1970-01-01")
        }
    } catch (e: Exception) {
        // empty
    }

fun aFunction() =
    try {
        if (System.currentTimeMillis() == 0L) {
            println("It is 1970-01-01")
        }
    } catch (e: Exception) {
        // empty
    }

And the IDE (lint) shows me an error even before compiling. Same error for the function.

Error message

To fix this issue you either introduce else statement OR redeclare this variable as a function (or update the function you have). This function will work fine as it always returns Unit even if you do not have any code in it.

fun aFunction() {
    try {
        if (System.currentTimeMillis() == 0L) {
            println("It is 1970-01-01")
        }
    } catch (e: Exception) {
        // empty
    }
}

When you use single-expression functions or getters you MUST return a value. That is why else part is required.

The issue is that Kotlin sees try {} catch {} construct as a "function" that returns a value, which is not the same as Java try {} catch {}. As a result compiler assumes that you "forgot" to code the else branches even if it is clearly the case of you not wanting to return any value. Kotlin sometimes is ludicrous.

i.e. you can write:

val t = try {
  "test"
} catch (e: Exception) {
  "error"
}
println(t)

As noted above, "Kotlin sometimes is ludicrous". In my case I was trying to do something in the catch statement:

fun x() {
  try {
    doSomething()
    doSomethingIfNoException()
  } catch (e:Exception) {
     if(c) doSomethingForException()
     else ""
  }
}

Kotlin insisted on the else in the catch. Putting the else"" was the easiest fix I could find.

Related