我想编写一个便利扩展来从Map中提取值,同时解析它们 . 如果解析失败,则该函数应返回默认值 . 这一切都很好,但我想告诉Kotlin编译器,当默认值不为null时,结果也不会为null . 我可以通过 @Contract
注释在Java中使用它,但它似乎在Kotlin中不起作用 . 可以这样做吗? Contract 不适用于扩展功能吗?这是kotlin的尝试:
import org.jetbrains.annotations.Contract
private const val TAG = "ParseExtensions"
@Contract("_, !null -> !null")
fun Map<String, String>.optLong(key: String, default: Long?): Long? {
val value = get(key)
value ?: return default
return try {
java.lang.Long.valueOf(value)
} catch (e: NumberFormatException) {
Log.e(TAG, e)
Log.d(TAG, "Couldn't convert $value to long for key $key")
default
}
}
fun test() {
val a = HashMap<String, String>()
val something: Long = a.optLong("somekey", 1)
}
在上面的代码中,IDE将突出显示 something
赋值中的错误,尽管使用非null默认值1调用 optLong
. 为了进行比较,这里是类似的代码,它通过Java中的注释和 Contract 测试可空性:
public class StackoverflowQuestion
{
@Contract("_, !null -> !null")
static @Nullable Long getLong(@NonNull String key, @Nullable Long def)
{
// Just for testing, no real code here.
return 0L;
}
static void testNull(@NonNull Long value) {
}
static void test()
{
final Long something = getLong("somekey", 1L);
testNull(something);
}
}
上面的代码没有显示任何错误 . 仅当删除了 @Contract
注释时,IDE才会警告对 testNull()
的调用可能为空值 .
2 回答
您可以通过使该函数通用来完成此操作 .
哪个可以这样使用:
这是有效的,因为
Long?
是Long
的超类型 . 通常会推断出类型,以便根据参数返回可空或不可空类型 .这将“告诉Kotlin编译器,当默认值不为null时,结果也不会为null . ”
很遗憾你不能在Kotlin 1.2或更低版本中这样做 .
然而,Kotlin正在开发
contract dsl
尚未通知,这是不可用的ATM(因为它们在stdlib中被声明为internal
)但你可以使用一些黑客在你的代码中使用它们(通过自己编译stdlib,使所有他们公开) .您可以在stdlib ATM中看到它们:
也许会有类似的东西
将来可以解决您的问题 .
解决方法
就个人而言,我建议你用NotNull
Long
替换default
的类型并将其称为result
是Long?
,仅当nullableLong
为空时才为空 .