Kotlin使用的Java库中的泛型和继承 [英] Generics and inheritance in Java library used from Kotlin
问题描述
我在实现Kotlin类时遇到问题,该类使用MockMvc库中的Java定义的泛型/接口类.
I'm having problem implementing a Kotlin class which uses Java-defined generics/interfaces classes from MockMvc library.
图书馆课程:
public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder<B>> extends MockMvcBuilder {
// ...
<T extends B> T defaultRequest(RequestBuilder requestBuilder);
// ...
}
@FunctionalInterface
public interface MockMvcBuilderCustomizer {
/**
* Customize the given {@code builder}.
* @param builder the builder
*/
void customize(ConfigurableMockMvcBuilder<?> builder);
}
我想用Java实现这一点:
I would like to implement this (in Java) :
@Component
public class ApiKeyHeaderMockMvcBuilderCustomizer implements MockMvcBuilderCustomizer {
@Override
public void customize(ConfigurableMockMvcBuilder<?> builder) {
RequestBuilder apiKeyRequestBuilder = MockMvcRequestBuilders.get("any")
.header("api-key-header", "apikeyvalue");
builder.defaultRequest(apiKeyRequestBuilder);
}
}
但是当我尝试用Kotlin重写上面的类时,我很难弄清楚应该在customize
的参数中以及在调用builder.defaultRequest
But when I try to rewrite the above class in Kotlin, I'm having troubles figuring out what generic constraint I should use both in customize
's parameter and when calling builder.defaultRequest
@Component
class ApiKeyHeaderMockMvcBuilderCustomizer : MockMvcBuilderCustomizer {
// is this generic right?
override fun customize(builder: ConfigurableMockMvcBuilder<*>) {
val apiKeyRequestBuilder: RequestBuilder =
MockMvcRequestBuilders.get("http://any")
.header("api-key-header", "apikeyvalue")
// won't compile, using Nothing compiles but fails at runtime
builder.defaultRequest<*>(apiKeyRequestBuilder)
}
}
从IntelliJ Idea中的Java复制粘贴代码将转换为以下Kotlin代码:
Copy-pasting the code from Java in IntelliJ Idea converts to this Kotlin code :
@Component
class ApiKeyHeaderMockMvcBuilderCustomizer : MockMvcBuilderCustomizer {
override fun customize(builder: ConfigurableMockMvcBuilder<*>) {
val apiKeyRequestBuilder: RequestBuilder = MockMvcRequestBuilders.get("any")
.header("api-key-header", "apikeyvalue")
builder.defaultRequest(apiKeyRequestBuilder)
}
}
在defaultRequest
下出现错误:
Type inference failed: Not enough information to infer parameter T in
fun <T : Nothing!> defaultRequest(requestBuilder: RequestBuilder) : T
Please specify it explicitly.
当我尝试使用Nothing
或Nothing?
作为defaultRequest
的通用参数时,我获得了运行时NullPointerException
来代替方法调用. defaultRequest方法的实现是:
When I try using Nothing
or Nothing?
in as generic parameter for defaultRequest
, I get runtime NullPointerException
in place of the method call. The implementation of the defaultRequest method is :
public abstract class AbstractMockMvcBuilder<B extends AbstractMockMvcBuilder<B>>
extends MockMvcBuilderSupport implements ConfigurableMockMvcBuilder<B> {
@Override
public final <T extends B> T defaultRequest(RequestBuilder requestBuilder) {
this.defaultRequestBuilder = requestBuilder;
return self();
}
@SuppressWarnings("unchecked")
protected <T extends B> T self() {
return (T) this;
}
}
推荐答案
编译器要求提供显式类型:
the compiler asks for the explicit type:
Type inference failed: Not enough information to infer parameter T in
fun <T : Nothing!> defaultRequest(requestBuilder: RequestBuilder) : T
Please specify it explicitly.
您可以这样指定它:
@Component
class ApiKeyHeaderMockMvcBuilderCustomizer<T :Nothing?> : MockMvcBuilderCustomizer {
override fun customize(builder: ConfigurableMockMvcBuilder<*>) {
val apiKeyRequestBuilder: RequestBuilder = MockMvcRequestBuilders.get("any")
.header("api-key-header", "apikeyvalue")
builder.defaultRequest<T>(apiKeyRequestBuilder)
}
}
这篇关于Kotlin使用的Java库中的泛型和继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!