Android 为什么系统显示';智能转换到';文件';是不可能的';在科特林?
在代码A1中,我使用了Android 为什么系统显示';智能转换到';文件';是不可能的';在科特林?,android,kotlin,Android,Kotlin,在代码A1中,我使用了let语句,因此我认为filenameofVideo.path将不会为空 但我得到以下错误,为什么 智能转换为“File”是不可能的,因为“filenameofVideo”是一个可变属性,此时可能已更改 此时,我必须使用代码A2 代码A1 private var filenameofVideo :File?=null filenameofVideo?.let { Navigation.findNavController(requireActivity(
let
语句,因此我认为filenameofVideo.path将不会为空
但我得到以下错误,为什么
智能转换为“File”是不可能的,因为“filenameofVideo”是一个可变属性,此时可能已更改
此时,我必须使用代码A2
代码A1
private var filenameofVideo :File?=null
filenameofVideo?.let {
Navigation.findNavController(requireActivity(), R.id.fragment_container)
.navigate(UIFragmentCameraDirections.actionCameraToVideo(filenameofVideo.path))
}
private val aa:String?=null
aa?.let {
print(aa)
}
代码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 var filenameofVideo :File?=null
filenameofVideo?.let {
Navigation.findNavController(requireActivity(), R.id.fragment_container)
.navigate(UIFragmentCameraDirections.actionCameraToVideo(filenameofVideo.path))
}
private val aa:String?=null
aa?.let {
print(aa)
}
代码B2
private val aa:String?=null
aa?.let{aa->
print(aa)
}
添加内容:
1:在代码C中,var aa可能在?let调用中访问它的那一刻和在let块中访问它的那一刻之间发生了更改(可能由另一个线程更改)
aa不为空时会启动代码C,aa为空时不会启动代码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)
}
代码类似于
private var aa: String? = null
aa?.let {
print(aa.length)
}
未编译,因为当安全调用?.let{}
块仅在aa
属性不为null时执行,当执行达到aa.length
时,aa
属性的值可能已在另一个线程中更改为null
另一方面,在本例中
private var aa: String? = null
aa?.let { aa ->
print(aa.length)
}
aa
属性的非空值在传递给let
的lambda的只读aa
参数中的安全调用后捕获
请注意,使aa
propertyval
代替示例B1中的var
也有助于消除错误,但这会导致let
块永远不会执行,因为初始化为null的私有val永远不会变为非null
关于示例C和D之间的区别的附加问题:
let{}
函数的执行方式没有区别。在这两种情况下,lambda函数仅在接收器表达式aa
不为空时启动,因为您使用的是?。
安全调用运算符
- 编译器不接受示例D,因为它无法确保lambda中引用的
aa
属性的值在执行到达该行时没有更改
代码如下
private var aa: String? = null
aa?.let {
print(aa.length)
}
未编译,因为当安全调用?.let{}
块仅在aa
属性不为null时执行,当执行达到aa.length
时,aa
属性的值可能已在另一个线程中更改为null
另一方面,在本例中
private var aa: String? = null
aa?.let { aa ->
print(aa.length)
}
aa
属性的非空值在传递给let
的lambda的只读aa
参数中的安全调用后捕获
请注意,使aa
propertyval
代替示例B1中的var
也有助于消除错误,但这会导致let
块永远不会执行,因为初始化为null的私有val永远不会变为非null
关于示例C和D之间的区别的附加问题:
let{}
函数的执行方式没有区别。在这两种情况下,lambda函数仅在接收器表达式aa
不为空时启动,因为您使用的是?。
安全调用运算符
- 编译器不接受示例D,因为它无法确保lambda中引用的
aa
属性的值在执行到达该行时没有更改
让我们把代码精简一点,以便更容易讨论:
这里的问题是,即使您调用了?.let
,编译器也无法保证文件名
在let
块中不为null。这是因为filename
是一个var
,并且var
的值可能在中被访问的那一刻与在let
块中被访问的那一刻之间发生了更改(可能是通过另一个线程)
因此,您必须自己处理空值的可能性。最简单的方法是在let
块中使用it
值,或者自己命名该值:
filename?.let { safe ->
action(safe.path)
}
此代码不起作用的原因是:
这里的变量是val
。这意味着它将是null
或非null,但无论如何都不能更改。因此,您和我可以阅读代码,并看到.let
块将永远不会执行。。。但如果它是,那就意味着aa
保证不为null,因此编译器可以智能地将其转换为不可为null的类型。让我们稍微精简一下代码,以便更容易讨论:
这里的问题是,即使您调用了?.let
,编译器也无法保证文件名
在let
块中不为null。这是因为filename
是一个var
,并且var
的值可能在中被访问的那一刻与在let
块中被访问的那一刻之间发生了更改(可能是通过另一个线程)
因此,您必须自己处理空值的可能性。最简单的方法是在let
块中使用it
值,或者自己命名该值:
filename?.let { safe ->
action(safe.path)
}
此代码不起作用的原因是: