Search code examples
genericskotlinnullable

Kotlin generics change return type


I have this method in Java I want to convert to Kotlin, but still use from both Java and Kotlin:

@Nullable
public static <T extends CharSequence> T nullIfEmpty(@Nullable final T t) {
   return TextUtils.isEmpty(t) ? null : t;
}

In another place I have a method that accepts Strings:

public static doSomething(@Nullable String foo) {}

Which I call in this way:

String foo = "";
doSomething(nullIfEmpty(foo)); // == doSomething(null); since foo is empty

After I converted the nullIfEmpty() to this Kotlin snippet:

fun <T : CharSequence> nullIfEmpty(t: T?): T? {
    return if (TextUtils.isEmpty(t)) null else t
}

Java no longer compiles complaining that there is an argument type mismatch - calling the function with a CharSequence when it expects a String.

What would be the correct syntax to fix this?


Solution

  • If you're on Java 8 (or later, I suppose), this code will actually work as you've presented it.

    On earlier versions (I assume you're on Android?), type inference is weaker, and you have to specify the generic type explicitly for this to work, like this:

    String foo = "   ";
    doSomething(K.<String>nullIfEmpty(foo));
    

    (I've wrapped the Kotlin function in an object called K and I'm calling it with that qualifier so that the type argument can be placed at the Java call site. I don't think you can provide a type parameter with a static import.)


    Side note: note that this is the implementation of TextUtils.isEmpty(), so it will not return true for a string like " ".

    /**
     * Returns true if the string is null or 0-length.
     * @param str the string to be examined
     * @return true if str is null or zero length
     */
    public static boolean isEmpty(@Nullable CharSequence str) {
        return str == null || str.length() == 0;
    }