英文:
Generics and inheritance in Java library used from Kotlin
问题
I understand that you want a translation of the code without the code part itself. Here's the translated explanation:
问题描述:
我在实现一个使用MockMvc库中的Java定义的泛型/接口类的Kotlin类时遇到问题。
库中的类:
public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder<B>> extends MockMvcBuilder {
// ...
<T extends B> T defaultRequest(RequestBuilder requestBuilder);
// ...
}
@FunctionalInterface
public interface MockMvcBuilderCustomizer {
/**
* 自定义给定的{@code builder}。
* @param builder builder
*/
void customize(ConfigurableMockMvcBuilder<?> builder);
}
我想要在Java中实现这个(在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
时遇到了困难。
@Component
class ApiKeyHeaderMockMvcBuilderCustomizer : MockMvcBuilderCustomizer {
// 是否正确使用了泛型?
override fun customize(builder: ConfigurableMockMvcBuilder<*>) {
val apiKeyRequestBuilder: RequestBuilder =
MockMvcRequestBuilders.get("http://any")
.header("api-key-header", "apikeyvalue")
// 不会编译,使用Nothing编译通过但在运行时失败
builder.defaultRequest<*>(apiKeyRequestBuilder)
}
}
从IntelliJ Idea中复制代码到Kotlin后,代码变成了这样:
@Component
class ApiKeyHeaderMockMvcBuilderCustomizer : MockMvcBuilderCustomizer {
override fun customize(builder: ConfigurableMockMvcBuilder<*>) {
val apiKeyRequestBuilder: RequestBuilder = MockMvcRequestBuilders.get("any")
.header("api-key-header", "apikeyvalue")
builder.defaultRequest(apiKeyRequestBuilder)
}
}
在defaultRequest
下有错误:
类型推断失败:无法从`fun <T : Nothing!> defaultRequest(requestBuilder: RequestBuilder) : T`中推断出参数T的足够信息
请明确指定它。
当我尝试在defaultRequest
的泛型参数中使用Nothing
或Nothing?
时,在方法调用处得到运行时的NullPointerException
。defaultRequest
方法的实现如下:
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;
}
}
请注意,Kotlin中的泛型参数和Java中的泛型参数之间可能存在一些差异,这可能导致类型推断失败和运行时错误。您可能需要查看MockMvc库的文档或寻求更多帮助以解决此问题。
英文:
I'm having problem implementing a Kotlin class which uses Java-defined generics/interfaces classes from MockMvc library.
Library classes:
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);
}
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);
}
}
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)
}
}
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)
}
}
With error under defaultRequest
:
Type inference failed: Not enough information to infer parameter T in
fun <T : Nothing!> defaultRequest(requestBuilder: RequestBuilder) : T
Please specify it explicitly.
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;
}
}
答案1
得分: 2
以下是翻译好的内容:
编译器要求明确的类型:
类型推断失败:在函数fun <T : Nothing!> defaultRequest(requestBuilder: RequestBuilder) : T中没有足够的信息来推断参数T。请明确指定它。
您可以像这样指定它:
@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)
}
}
英文:
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.
you can specify it like this:
@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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论