Search code examples
javakotlinoverloadingnullableoverload-resolution

How do I force a Java call to overloaded Kotlin method accepting a non-nulllable parameter?


In Kotlin, I have two overloaded methods defined on an object. They have the same signature except that in one case, a parameter is nullable and in the other case, that same parameter is not. Based on if the passed in parameter is nullable or not, one overload is chosen over the other:

fun getBooleanPropertyValue(key: String, dflt: Boolean? = null) : Optional<Boolean> {
}

fun getBooleanPropertyValue(key: String, dflt: Boolean) : Boolean {
}

I hope it is clear what is going on here. If I can supply a non-nullable default value for a property, then the class can always return a non-null value for that property, and so it returns it directly. If I can't supply a non-nullable default, then the class returns an Optional because it can't be sure it can pass back a non-null object.

This all works great in Kotlin, but now I want to call the non-nullable version from Java. I have something like this:

static final Boolean defaultIsDisabled = false;
Boolean isDisabled = propSource.getBooleanPropertyValue("isDisabled", defaultIsDisabled);

I get an error here because Java calls the method that accepts a non-nullable default, and so therefore returns an Optional, and I'm trying to assign that to a Boolean. But in this case, the default I'm passing can never be null and I want to get back a Boolean directly.

I know Java can call the other method because this works:

Boolean isDisabled = propSource.getBooleanPropertyValue("isDisabled", false);

I've tried using various flavors of the @Notnull/@Nonnull annotations on the defaultIsDisabled value to tell Java it can never be null, but I can't figure out how to get Java to call the version of the method that returns a bare Boolean.

Can anyone tell me how to get Java to call the version of this method that accepts a non-nullable default value while supplying that value via a variable?


Solution

  • A non-nullable Boolean is simply boolean in Java. To call the non-null overload, simply use a cast:

    static final Boolean defaultIsDisabled = false;
    boolean isDisabled = propSource.getBooleanPropertyValue("isDisabled", (boolean) defaultIsDisabled);
    

    This only works because Kotlin optimizes the second method to accept a boolean rather than a Boolean, so the signatures of the two methods are different in the generated bytecode. In the case of equivalent methods accepting a String parameter, there's no way to call either of these methods from Java. Kotlin creates two methods with identical signatures, and when you attempt to call one of them from Java, you get an "Ambiguous method call" error.