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
访问Android传感器的惰性非Null属性时为Null属性_Android_Kotlin_Kotlin Android Extensions - Fatal编程技术网

访问Android传感器的惰性非Null属性时为Null属性

访问Android传感器的惰性非Null属性时为Null属性,android,kotlin,kotlin-android-extensions,Android,Kotlin,Kotlin Android Extensions,当通过lazy初始化类型为Sensor的val时,编译器忽略返回的值可以是null private val sensorManager by lazy { getSystemService(Context.SENSOR_SERVICE) as SensorManager } private val proximitySensor: Sensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) } 注意:val被声

当通过
lazy
初始化类型为
Sensor
val
时,编译器忽略返回的值可以是
null

private val sensorManager by lazy { getSystemService(Context.SENSOR_SERVICE) as SensorManager }

private val proximitySensor: Sensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) }
注意:
val
被声明为
传感器,而不是
传感器?

private val sensorManager by lazy { getSystemService(Context.SENSOR_SERVICE) as SensorManager }

private val proximitySensor: Sensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) }

sensorManager.getDefaultSensor(Sensor.TYPE_approxity)
也可以返回
null
,并且该方法没有使用
@Nullable
注释,因此在编译时无法对其进行检查


另外,Android Studio在检查null时会发出警告,因为我们没有将其声明为
传感器?

可空的
赋值给
val
非空的
时,它不应该引发编译时错误吗


当访问值
proximitySensor
时,如果该值为空,则会产生预期的运行时异常。
'java.lang.String android.hardware.Sensor.getName()'在空对象引用上

Kotlin标准库参考中的
lazy()
,如下所示:

  • lazy()
    返回存储lambda初始值设定项的
    lazy
    实例
  • getter的第一个调用执行传递给
    lazy()
    的lambda,然后 存储其结果
  • 随后,getter执行返回存储的值
  • 在进行赋值时不应该抛出异常吗 当我们尝试访问它时

    运算符设置值(
    有吗?,
    属性:KProperty,值:字符串
    ) {
    //分配
    //分配发生时,此时应生成异常
    }
    
    多亏了你的问题,现在这是一个很好的回答


    此答案的早期内容: 我对你的问题做了一个MCVE:

    val sensorManager = SensorManager()
    val proximitySensor: Sensor by lazy { sensorManager.sensor }
    
    fun main(args: Array<String>) {
        println(proximitySensor)
    }
    
    而且。。。你猜怎么着?它打印
    null
    。我称之为“Kotlin bug”:


    你问:

    当赋值时,而不是当我们试图访问它时,不应该抛出异常吗

    对于
    惰性
    委托,只有当您第一次访问属性时才会发生赋值。这将传播到
    SynchronizedLazyImpl.value
    getter,其中包含众所周知的双重检查惰性init习惯用法,并且这是您提供的初始值设定项块唯一运行的时间

    即使没有详细讨论,
    延迟
    委托的本质是将初始化推迟到可能的最晚时间,这是第一次属性访问。正确的实现将确保在不可为null的属性的计算完成之前引发异常。不幸的是,当前的实现不正确。

    是否应该有编译时错误? 当将可为null的值分配给非null的val时,它不应该引发编译时错误吗

    是的,但这里不是这样的情况在本例中,您将a赋值给您的值,并告诉编译器将其视为不可为空。应该有一个运行时错误
    IllegalStateException
    ——正如@MarkoTopolnik指出的,这是一个bug

    缺陷 此错误已被覆盖。这里有一个与学员直接相关的问题。 还有一个讨论主题和一些可运行的示例

    何时将引发运行时异常? 当您使用
    proximitySensor
    时,将触发该错误,该方式需要一个不可为空的值,例如:

    val s: Sensor = proximitySensor
    proximitySensor.someMethod()
    println(proximitySensor.someProperty)
    
    但是当属性初始化时,这不会引发异常!我们可以解决这个问题

    为什么首次初始化Lazy属性时没有错误?
    由于
    sensorManager.getDefaultSensor(Sensor.TYPE\u approxity)
    是用java实现的,因此它返回一个值。因此,惰性委托的类型为,
    Lazy

    懒惰类运行初始值设定项lambda。保存lambda的结果,然后以类型
    T
    返回,即
    传感器

    解决方案 如果在调用
    lazy
    函数时显式声明类型params:

    private val proximitySensor: Sensor by lazy<Sensor> { sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) }
    
    在惰性初始值设定项内提供默认值
    正如您所提到的,
    sensorManager.getDefaultSensor(Sensor.TYPE\u approxity)
    可能返回null。我们可以返回一个默认值:

    val proximitySensor: Sensor by lazy {
      sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) ?: SOME_DEFAULT_VALUE 
    }
    
    关于平台类型的注释 Kotlin中的平台类型允许您(调用方)决定类型是可为null还是不可为null,从而使使用Java更加实用。假设Java中的所有内容都可以为null,这意味着您将不得不进行大量痛苦的null检查,即使Java代码从不返回null

    *注意:如果您正在编写Java代码,可以使用
    @Nullable
    @NonNull
    注释向Kotlin编译器以及其他静态分析工具提供元数据。Spring框架等库


    以下是Kotlin开发人员Andrey Breslav的文章,他深入讲述了平台类型的互操作性设计决策。

    因为这是一个返回
    传感器的Java API调用@m0skit0,但这里没有赋值<代码>惰性
    是一个属性委托。当您取消引用
    val
    时,将调用其
    get()
    方法。但是,如果由于取消引用
    proximitySensor
    ,而得到
    null
    ,这显然是Kotlin的错误。sensorManager.getDefaultSensor(Sensor.TYPE_Proximition)没有nullability注释,因此Kotlin相信您关于它是否可以为null的问题。@MarkoTopolnik我认为它的意思是“委派时间”其中,
    proximitySensor
    被“分配”了一个
    lazydegate
    ——它发生在编译时。@harsh\u v良好的编辑。我已经更新了关于懒惰n的答案
    private val proximitySensor: Sensor? by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) }
    
    val proximitySensor: Sensor by lazy {
      sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) ?: SOME_DEFAULT_VALUE 
    }