Kotlin使用的Java库中的泛型和继承 [英] Generics and inheritance in Java library used from Kotlin

查看:573
本文介绍了Kotlin使用的Java库中的泛型和继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在实现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.

当我尝试使用NothingNothing?作为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆