Home > Blockchain >  Return from Try/Catch block in Kotlin
Return from Try/Catch block in Kotlin

Time:06-24

Kotlin newbie here...

So I have a method that returns a userDefined object

fun doSomethingMagical(param1: String): UserDefinedObject {
     val result = UserDefinedObject
     // execute some code 
     try {
       ....
       if(some expression){
        val temp = //some code
        result = temp
      }
       return result
     } catch(e : Exception){
     null
     }
}

the above method gives me 2 error:

Variable 'result' must be initialized

A 'return' expression required in a function with a block body ('{...}')

Any help is welcome!

CodePudding user response:

Here's a solution, probably not the best one though:

fun doSomethingMagical(param1: String): UserDefinedObject? {
 var result = UserDefinedObject() 
 //assuming this object has no properties
 //if it does you much provide them to initialize it
 ...
 try {
   ....
   if(some expression){
    val temp : UserDefinedObject = //some code
    result = temp
 } catch(e : Exception){
    return null
 }
  return result
}

A better one, depending on whether or not you need the result before the try (I'm assuming you don't), you may be able to do it this way:

fun doSomethingMagical(param1: String): UserDefinedObject? {
   return try {
     whateverSomeCodeIs() // returns a UserDefinedObject
  } catch(e : Exception){
    null
  }
}

Or this way:

fun doSomethingMagical(param1: String): UserDefinedObject? {
       try {
         return whateverSomeCodeIs() // returns a UserDefinedObject
      } catch(e : Exception){
        return null
      }
    }

Or this way which will imply the return type and doesn't require "return" explicitly:

fun doSomethingMagical(param1: String) = try { whateverSomeCodeIs() } catch(e: Exception) { null }

If you don't want it to be nullable (which is what the "?" indicates) then you would need to return a UserDefinedObject in the catch, allow the exception to be thrown and catch it later, or ensure that an exception can not be thrown.

I'd also recommend that you check out the Kotlin docs. They are pretty informative. Here's a link to their Exceptions section.

CodePudding user response:

So a bit of background - a try block is what you wrap some code in when that code might throw an Exception, which you can think of as a kind of error. If an exception is ever thrown, execution of that code stops and the program starts to back out of the chain of functions it called to get where it is. If nothing catches that exception, it'll eventually crash the program.

So to be safe, you can wrap code in a try block (which implies that it could throw) and add a catch block to deal with the expected exception. If an exception gets thrown, it backs out of the try block, but if there's a catch that handles that exception type, it jumps to that block and carries on executing from there - it's handled, everything can continue!

For example, if you wanted to read from a file, there's a possibility of a problem where it's just not available for some reason, and the reading code could throw an IOException. You'd catch that exception type, and handle the situation gracefully instead of letting it crash, that kind of thing.

So here's the basic flow of your code:

fun doSomethingMagical(param1: String): UserDefinedObject {
     val result = UserDefinedObject
     // execute some code 
     try {
       ....
       return result
     } catch(e : Exception){
        null
     }
}

What you're basically saying is, you're going to try to execute some code, which eventually ends with a return statement. But that implies there's a possibility of an exception, ending that block early - you might never hit that return. In which case you jump to the catch block (which handles all types of Exception), do whatever is in there, and then exit the whole try/catch and carry on with the rest of the doSomethingMagical function.

But if that happens, you never hit a return. If an exception is thrown (which you're explicitly saying might happen by using a try block - that's you saying you'll handle it) then you won't reach a return statement - that's why you're getting error messages like A 'return' expression required in a function with a block body or whatever. There's a possible flow of execution that doesn't reach one, and that's not allowed


So there's two typical ways to do this - you could either return a value in the try, and return a fallback value in the catch:

try {
    ...
    // return from the function right here
    return result
} catch(e: Exception) {
    // or if there was a problem, return from here
    return fallbackValue
}

or just initialise a mutable var with the default value, return it at the end of the function, and maybe change it inside the try (if that succeeds):

var result = someDefaultValue
try {
    // do things, set new result
    result = somethingElse
} catch (e: Exception) {
    // whatever handling you need to do, having this here ensures code execution
    // continues if there's any problem in the try block
}
// whatever the value of result is (default or if it's been changed), return it here
return result

And the latter looks like what you're going for since you're initialising a result value at the start of the function (can't be a val if you want to change it though)

  • Related