首页 > 解决方案 > 为什么系统在 Kotlin 中显示“Smart cast to 'File' is not possible”?

问题描述

在代码 A1 中,我使用了该let语句,所以我认为它不会为空filenameofVideo.path

但是我收到以下错误,为什么?

智能转换为“文件”是不可能的,因为“filenameofVideo”是一个可变属性,此时可能已更改

此时,我必须使用代码 A2。

代码 A1

private var filenameofVideo :File?=null

filenameofVideo?.let {
          Navigation.findNavController(requireActivity(), R.id.fragment_container)
               .navigate(UIFragmentCameraDirections.actionCameraToVideo(filenameofVideo.path))
}

代码 A2

private var filenameofVideo :File?=null

filenameofVideo?.let {filenameofVideo ->
        Navigation.findNavController(requireActivity(), R.id.fragment_container)
            .navigate(UIFragmentCameraDirections.actionCameraToVideo(filenameofVideo.path))
}

而且,我发现代码 B1 和代码 B2 都是正确的。为什么代码 B1 正确而代码 A1 错误?

代码 B1

   private val aa:String?=null
   aa?.let {
            print(aa)
        }

代码 B2

private val aa:String?=null    
   aa?.let{aa->
           print(aa)
      }

添加内容:

1:在代码 C 中,在 ?.let 调用中访问 var aa 和在 let 块中访问它的那一刻之间,var aa 可能已更改(可能被另一个线程更改)。

当aa不为null时会启动代码C,而当aa为null时不会启动代码C,对吗?

2:在代码D中(我假设编译器接受它),无论aa是否为null,函数总是被启动,它不能被接受,所以系统会中断,对吗?

代码 C

private var aa: String? = null    
aa?.let { kk ->
    print(kk.length)
}

代码 D

private var aa: String? = null    
aa?.let {
    print(aa.length)
}

标签: androidkotlin

解决方案


让我们稍微精简一下您的代码,以便更容易讨论:

private var filename :File?=null

filename?.let {
    action(filename.path)
}

这里的问题是,即使您调用?.let了 ,编译器也不能保证块filename内不为空let。这是因为filenameis a var,并且在调用中访问它的那一刻和在块中访问它var的那一刻之间,它的值可能已经更改(可能由另一个线程) 。?.letlet

因此,您必须自己处理 null 的可能性。最简单的方法是使用块it内的值let,或者自己命名该值:

filename?.let { safe ->
    action(safe.path)
}

此代码确实有效的原因:

private val aa:String?=null
aa?.let {
    print(aa)
}

是不是这里的变量是 a val。这意味着它要么为null空,要么为非空,但无论哪种方式,它都不能改变。所以你和我可以阅读代码并看到该.let块永远不会被执行......但如果它以某种方式执行那将意味着它aa保证不为空,因此编译器可以将它智能转换为非可空类型。


推荐阅读