1

I need to inform in my class code that the function passed by parameter (convertorCall) can throw an exception.

suspend operator fun <T> invoke(
    convertorCall: () -> T
): T?

For example, if this function were as a method of a class I could do this:

@Throws(JsonSyntaxException::class)
suspend fun <T> convertorCall(): T

However, as said before, I need this to be informed in the function passed by parameter of the invoke function.

I tried this:

suspend operator fun <T> invoke(
    @Throws(JsonSyntaxException::class) convertorCall: () -> T
): T?

But a syntax error is generated:

This annotation is not applicable to target 'value parameter'

Pierre Vieira
  • 2,252
  • 4
  • 21
  • 41
  • Is your goal here to attain compatibility with java? Because the @Throws annotation is exclusively for that. If it's kotlin it should just be a comment, which you can put on your lambda as well. Also unless I'm confused I don't see how it makes sense to mark that lambda since there isn't really any reason to be sure that it can throw that exception, that would depend on the caller. – somethingsomething Jul 28 '22 at 15:36

1 Answers1

1

Kotlin doesn't have checked exceptions, i.e. ones where a function explicitly states what it could throw, and any callers are required to wrap the call in a try/catch to deal with that possibility. Or not catch it, state that they themselves might produce that exception, and pass the responsibility to handle it up the chain.

That link explains the rationale, and links to some sources talking about the issue, but it's basically just how things are done (or not done) in Kotlin. There's a @Throws annotation for interoperability with other languages where checked exceptions is how things are done, but it's not used in Kotlin itself.

If you want to inform the caller that an exception could be thrown, you're supposed to put it in the documentation comment for the function. There's a @throws tag (or an @exception one if you like) for that purpose, but like it says:

Documents an exception which can be thrown by a method. Since Kotlin does not have checked exceptions, there is also no expectation that all possible exceptions are documented, but you can still use this tag when it provides useful information for users of the class.

So it's purely informational really, and the user can choose to handle or not handle those potential exceptions - it's not required. And if you're writing your own functions, you might want to consider whether they should throw an exception to the caller at all during normal, anticipated behaviour, or if they should return some kind of error value (like null) or an error type (e.g. a sealed class that has some kind of failure subclass as well as success types).

// You could return this type instead of throwing an exception
sealed class Result<T> {
    class Conversion<T>(data: T) : Result<T>()
    class Error<T>(message: String) : Result<T>()
}

Basically, if you know a specific thing can go wrong during normal operation, is it really exceptional? Or just another kind of result to inform the caller about so it can take action if it needs to?

cactustictacs
  • 17,935
  • 2
  • 14
  • 25