Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
I';我在kotlin安全呼叫中收到过载解析模糊错误_Kotlin_Nullable - Fatal编程技术网

I';我在kotlin安全呼叫中收到过载解析模糊错误

I';我在kotlin安全呼叫中收到过载解析模糊错误,kotlin,nullable,Kotlin,Nullable,我有一个可为空的字符串变量ab。如果我在为toUpperCase赋值null后通过安全调用操作符调用它,kotlin会给出错误 fun main(args: Array<String>){ var ab:String? = "hello" ab = null println(ab?.toUpperCase()) } fun main(args:Array){ 变量ab:字符串?=“您好” ab=null println(ab?.toUpperCase())

我有一个可为空的字符串变量
ab
。如果我在为
toUpperCase
赋值null后通过安全调用操作符调用它,kotlin会给出错误

fun main(args: Array<String>){
    var ab:String? = "hello"
    ab = null
    println(ab?.toUpperCase())
}
fun main(args:Array){
变量ab:字符串?=“您好”
ab=null
println(ab?.toUpperCase())
}
错误:(6,16)
重载解析歧义:
@仅限在线公共 内联fun Char.toUpperCase():在kotlin.text中定义的字符
@InlineOnly public inline fun String.toUpperCase():在kotlin.text中定义的字符串


这里的问题是什么?

我不确定,但这似乎是一个错误,因为智能强制转换(to
Nothing?
,每个可空类型的子类型)。这一个有效:

fun main(args: Array<String>) {
    var ab: String? = "hello"
    ab = makeNull()
    println(ab?.toUpperCase())
}

fun makeNull(): String? = null
fun main(args:Array){
变量ab:字符串?=“您好”
ab=makeNull()
println(ab?.toUpperCase())
}
fun makeNull():字符串?=无效的

唯一的区别是:编译器不直接知道
null
赋值,这似乎导致了示例中的错误。但是,你的可能也会起作用

它看起来真的像个虫子。类型
String?
在赋值
null
时以某种方式丢失,因此您必须明确地告诉编译器它应该处理
字符串?

fun main(args: Array<String>){
    var ab: String? = "hello"
    ab = null
    println((ab as String?)?.toUpperCase()) // explicit cast

    // ...or

    println(ab?.let { it.toUpperCase() }) // use let
}
fun main(args:Array){
变量ab:字符串?=“您好”
ab=null
println((ab作为字符串?.toUpperCase())//显式强制转换
//…或
println(ab?.let{it.toUpperCase()})//使用let
}
我认为这是由于Kotlin使用了此功能。换句话说,Kotlin能够推断在这行代码之后:

变量
ab
的类型只是
null
(这不是您在Kotlin中可以使用的实际类型-我只是指允许值的范围),而不是
String?
(换句话说,不可能
ab
包含
字符串


考虑到toUpperString()扩展函数仅为Char和String(而不是Char?或String?)定义,因此无法在两者之间进行选择

要避免这种行为,请参阅其他人提出的答案(例如,显式转换为字符串?),但这对我来说显然是一个功能(非常有用),而不是一个bug。

如本文所述:

x=y使x成为赋值后的y类型

ab=null
可能会将
ab
转换为
Nothing?
。如果您检查
ab是否为空?
它确实是
true

var ab: String? = "hello"
ab = null
println(ab?.toUpperCase())
println(ab is Nothing?) // true
由于
Nothing?
是所有类型(包括
Char?
String?
)的子类型,因此它解释了为什么会出现
重载解析模糊性
错误。此错误的解决方案将是Willi Mentzel在中提到的,在调用
toUpperCase()
之前,将
ab
转换为
String
类型。
评论: 当一个类实现了两个接口,并且两个接口都有相同签名的扩展函数时,就会发生这种错误:

//interface
interface A {}
interface B {}

//extension function
fun A.x() = 0
fun B.x() = 0

//implementing class
class C : A, B {}

C().x()    //Overload resolution ambiguity
(C() as A).x()    //OK. Call A.x()
(C() as B).x()    //OK. Call B.x()

我反编译了你的函数,我想:在你做出
ab=null
的那一刻之后,编译器将智能地对它进行转换,在
ab
的每一次出现中放入
null
(acost\u null)。然后as
null
没有类型。无法推断
toUpperCase()
的接收器类型

这是从kotlin字节码生成的java等效代码:

public final void main(@NotNull String[] args) {
   Intrinsics.checkParameterIsNotNull(args, "args");
   String ab = "hello";
   ab = (String)null;
   Object var3 = null;
   System.out.println(var3);
}

这似乎是一个应由kotlin团队解决的问题。

“变量ab的类型为空”空不是一个类型!“考虑到toUpperString()扩展函数仅为Char和String(而不是Char?或String?)定义,因此无法在两者之间进行选择。”使用了安全调用运算符,因此在ab为null时,toUpperString()永远不会在ab上调用。“…ab不可能包含字符串)“如果我分配ab=”hello2“在空赋值之后。突然又出现了一种方式,它再次包含字符串。是的,没有可以使用的
null
类型,但在进行类型推断时,编译器可能会在下面使用“类”
null
类型(基本上,想象一下Typescript,其中不允许显式使用
null
)。当然,这只是一个假设,但实际行为与这个假设相当一致。我们需要Kotlin开发团队中的某个人的评论,以澄清smart Cast实际上是如何工作的。是的,编译器可以决定无论如何不调用
toUpperCase()
,因此它可以完全忽略整个过程。然而,Kotlin开发人员决定进行这项检查。这是否是一个好的决定是个人偏好的问题,对我来说,进行这样的检查似乎相当合理。等等,
ab
不是已经在第一行定义为可为空的字符串了吗?那么,为什么要将一个字符串转换为字符串呢?是否有必要?@donfuxx,因为
ab
的类型被智能转换为
Nothing?
Nothing?
String?
Char?
的子类型。同时,还有一个扩展函数
toUpperCase()
声明为receiver type
String
Char
。因此,我们必须告诉编译器,我们希望调用扩展函数,并将
String
作为接收器。天哪,刚刚在调试器中完成了问题的代码,并且
ab为Nothing?
计算为true。所以“聪明”的演员阵容发生了我想。。但“哑巴”演员可能是个更好的名字;-)我更喜欢像其他答案一样将其视为一个kotlin bug,但仍然竖起大拇指,因为这个答案有助于分析:-)很好的分析,这完全是错误的sense@donfuxx这是一个非常复杂的案例。您什么时候为某个对象分配
null
,然后执行安全调用?无论如何都不会执行该调用。如果有的话,我更喜欢一个编译器警告
public final void main(@NotNull String[] args) {
   Intrinsics.checkParameterIsNotNull(args, "args");
   String ab = "hello";
   ab = (String)null;
   Object var3 = null;
   System.out.println(var3);
}