没有任何泛型的kotlin错误的可空性推断

时间:2018-12-23 22:16:08

标签: java spring kotlin

在春季MVC(5.1.3)中,我正在尝试做:

val url : String? = null
val matcher: ResultMatcher = MockMvcResultMatchers.forwardedUrl(url)

第二行出现编译错误。

从intellij(kotlinc-jvm 1.3.11):

Error:(230, 56) Kotlin: Null can not be a value of a non-null type String

或从gradle(kotlin 1.2.71):

 Type mismatch: inferred type is String? but String was expected

spring方法的Java源代码为:

/**
 * Asserts the request was forwarded to the given URL.
 * <p>This method accepts only exact matches.
 * @param expectedUrl the exact URL expected
 */
public static ResultMatcher forwardedUrl(String expectedUrl) {
    return result -> assertEquals("Forwarded URL", expectedUrl, result.getResponse().getForwardedUrl());
}

intellij显示javadoc:

org.springframework.test.web.servlet.result.MockMvcResultMatchers @NotNull 
@Contract(pure = true) 
public static org.springframework.test.web.servlet.ResultMatcher forwardedUrl(@Nullable String expectedUrl)

那为什么编译器仍然需要非空类型以及如何绕过该要求?

2 个答案:

答案 0 :(得分:5)

MockMvcResultMatchers.forwardedUrl的参数上没有显式的可空性注释,因此它将默认为@NonNullApi,如package-info.java所示:

/**
 * Contains built-in {@code ResultMatcher} and {@code ResultHandler} implementations.
 * <p>Use {@link org.springframework.test.web.servlet.result.MockMvcResultMatchers}
 * and {@link org.springframework.test.web.servlet.result.MockMvcResultHandlers}
 * to access instances of those implementations.
 */
@NonNullApi
@NonNullFields
package org.springframework.test.web.servlet.result;

import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

无法描述Java中的可空性,因此默认情况下将StringString?都传递到接受String的Java方法中是可行的。但是,Kotlin编译器采用不同类型的可空性注释(例如javax.annotation.*,Android的注释,Spring的注释),以允许Java代码向Kotlin调用者提供可空性信息。

如何绕过这个?你不能您传递的参数类型错误  -StringString?在Kotlin中是不同的类型。

答案 1 :(得分:-1)

val url : String? = null,然后变量url null,具有可空类型String?,因为它是不可变的val。但是我认为我们应该忽略这个问题的可变性。

要使其“非无效”,可以使用Elvis opeator

val matcher: ResultMatcher = MockMvcResultMatchers.forwardedUrl(url ?: "")

或将“默认”值替换为所需的值。