Recommendations for null checking with Java interop


#1

Hi all,

What would be the recommended way to do null-checking for all function arguments? I have several Kotlin functions that are called from Java code, and as a result all the arguments can be null. I started by creating a generic validation function

fun isValidInput(vararg inputs: Any?) = inputs.all { it != null }

which seems to work, but the compiler fails to infer that the arguments are non-null and I need to resort to the !! operator.

fun foo(a: BigDecimal?, b: BigDecimal?, c: BigDecimal?, d: BigDecimal?): BigDecimal? {
    if (isValidInput(a, b, c, d))
        a!! + b!! + c!! + d!!
    else null
}

This seems ugly and error-prone but the alternative of adding explicit null-checks for each parameter in the if condition also quickly gets verbose and tedious when you have many arguments with lengthy names.

Are there any other options for performing the null check? Maybe some way of instructing the compiler that the values inside the if block really are non-null? Thanks in advance for any insight!


#2

I think that the design style which allows any function parameters to be null and returns null if any parameter was null is not very good in any language, be it Java, Kotlin or any other. Such a design delays the possibility of detecting errors because the code will keep performing nonsensical null-returning calls instead of failing quickly at the exact moment when required data has not been provided.

Even in pure Java projects, you can define the contract of your function so that it requires all or some of its arguments to be non-null. In Java, you’d need to validate the arguments manually, and in Kotlin, you don’t need to because the compiler will automatically generate null check assertions for all public method parameters that have a non-null type.


#3

Thanks for your reply! In general I fully agree with what you’re saying, but in this case the values are ultimately coming from user input and the user is free to input partial data at any given moment (getting then results only for parts that actually can be calculated, of course). So this really is a garbage-in, garbage-out kind of scenario.

I can certainly add the null checks to the Java side before calling the Kotlin code (and admittedly that would probably be a good idea) but ideally I would like to perform Maybe monad like computation where I could freely operate on input values and the computation would automatically short-circuit to None (or null) in case one of the values is absent. In the vein of, say, F#:

maybe {
    let x = 12
    let! y = Some 11
    let! z = Some 30
    return x + y + z
}

I suppose that can’t be easily achieved with Kotlin currently?


#4

No, there is no such feature in Kotlin at this time. The best you can do is something like that:

fun <T1 : Any, T2 : Any, R> let2(a: T1?, b: T2?, callback: (T1, T2) -> R): R? =
    if (a != null && b != null)
        callback(a, b)
    else
        null

Repeat for N > 2 as desired.


#5

That may actually be quite sufficient solution for my needs at the moment. Thanks a lot for the tip!