I encountered an issue when I used kotlin and retrofit2,The generic parameters of kotlin are converted to wildcards(?),but not in java.
now, I need a parameter Map<String, Object>
(The key is the String type, the value is not fixed) in java,convert to kotlin code is Map<String, Any>
.
But retrofit treats them differently.
Map<String, Object>
in java be compiled into [java.util.Map<java.lang.String, java.lang.Object>]
,and works correctly.
Map<String, Any>
in kotlin be compiled into [java.util.Map<java.lang.String, ?>]
,and the retrofit2 throws parameterError(Parameter type must not include a type variable or wildcard).
1、Retrofit related code
public ServiceMethod build() {
……
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType);
}
……
}
……
}
Utils.hasUnresolvableType(parameterType) method is quoted as follows
final class Utils {
……
static boolean hasUnresolvableType(Type type) {
……
if (type instanceof WildcardType) {
return true;
}
……
}
……
}
2、interface in java, I need a parameter Map<String, Object>
(The key is the String type, the value is not fixed), it be compiled into [java.util.Map<java.lang.String, java.lang.Object>]
,and works correctly.
@GET("/index.html")
Observable<ResponseBody> getQueryMap(@QueryMap Map<String, Object> params);
3、interface in kotlin,I need a parameter Map<String, Any>
(The key is the String type, the value is not fixed), but it be compiled into [java.util.Map<java.lang.String, ?>]
,and the retrofit2 throws parameterError(Parameter type must not include a type variable or wildcard).
@GET("/index.html")
fun getQueryMap(@QueryMap paramsMap: Map<String, Any>): Observable<ResponseBody>
The type parameter lets you specify exactly that—instead of “This variable holds a list,” you can say something like “This variable holds a list of strings.” Kotlin's syntax for saying “a list of strings” looks the same as in Java: List<String> . You can also declare multiple type parameters for a class.
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).
"Out" keyword is extensively used in Kotlin generics. Its signature looks like this − List<out T> When a type parameter T of a class C is declared out, then C can safely be a super type of C<Derived>. That means, a Number type List can contain double, integer type list.
You simply have to add @JvmSuppressWildcards
to your interface name.
@JvmSuppressWildcards internal interface WebService { ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With