Over the past few months my team has been steadily moving our code over to Kotlin
. It’s been a joy to get to work with such a succinct, yet expressive language. However, I have spent needless hours attempting to debug issues in my application that were all solved with the addition of this one thing: @JvmSuppressWildcards
.
The annotation @JvmSuppressWildcards, is used to instruct the compiler to generate or omit wildcards for type arguments. Why is this the key to stopping endless debugging?
It’s related to how Kotlin generates code in order to work with Java. The technical term is declaration site-variance. In the simplest terms Kotlin will take your code that looks like this:
fun recordActionsWithGps(@Body gpsRequests: List<GpsRequest>)
And turn it into this:
fun recordActionsWithGps(@Body gpsRequests: List<? extends GpsRequest>)
However, this may not always be what you want. For instance, if you have a Java class that implements the Interface
containing this method, the compiler will complain. Typically you may see something like 'Method does not override method from its superclass'
.
You have to take some type of corrective action before being able to move forward. The best way to figure out what’s happening in your case, is to view the decompiled code. Here’s what it will look like:
By checking the declaration you can see if the ? extends
is being tacked on. If so, then you can simply change your parameter declaration to the following:
fun recordActionsWithGps(@Body gpsRequests: List<@JvmSuppressWildcards GpsRequest>)
And the ? extends
will not be added. It’s your way of telling the compiler you know what you’re doing. Here are a few other cases where our favorite annotation has come in handy: with Multi-Binding Maps in Dagger 2
, and then when working with custom GSON
Adapters.
Have you had to use @JvmSuppressWildcards? If so, what’s the use-case? Comment below.
Special thanks to: @donnfelker and @trionkidnapper for reviewing this post!