在扩展Java类时,在Kotlin中处理null情况的最佳方法是什么?

时间:2016-06-24 20:50:12

标签: kotlin

当Kotlin的某些事情无效时,我真的陷入困境。当值不能为空时 - 很明显。但是默认情况下,当某些东西可以为null时如何处理情况。看一下这个例子:

abstract class MapActivity: AppCompatActivity(), OnMapReadyCallback {

    lateinit var map: GoogleMap

    fun initializeMap() {
        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }

    override fun onMapReady(map: GoogleMap?) {
        this.map = map //error here
    }
}

所以我应该这样处理这种情况:

override fun onMapReady(map: GoogleMap?) {
        if (map != null) 
            this.map = map
    }

但是如果地图是 null 怎么办?在这种情况下我该怎么办?我在使用java时遇到过这个问题。

好的,在java中,如果map为null,我们将获得NPE。

对我而言,NPE总比没有好。程序崩溃,这对我来说是一个信号,有些事情是错的,我应该修复它。通过这种方式,我甚至无法追踪我的问题及其发生的原因。 是的,我们可以这样写:

override fun onMapReady(map: GoogleMap?) {
    if (map != null) {
        this.map = map
    } else {
        Log.d("Activity","MapIsNull")
    }    
}

这个代码中有一些含义,是的。 但是我仍然对整个零安全问题犹豫不决。 安全调用例如是奇怪的东西,它产生null和(在我看来)heisenbugs或很难捕获的bug。

有人可以向我解释这里发生了什么,以及使用零安全的最佳做法是什么。

我很确定这件事很有用,因为我不像JB那样聪明

3 个答案:

答案 0 :(得分:4)

OnMapReadyCallback的文档明确说明它提供了GoogleMap"的非空实例。因此,onMapReady方法的参数类型应使用非null类型。

请注意,在Kotlin中实现Java接口时,可以选择是将实现方法的参数声明为nullable还是非null。 IDE将它们标记为可为空,因为它是安全的默认值,但如果您需要它,则可以将它们更改为非null。

答案 1 :(得分:-1)

关于处理空值:让我们假设你需要一个方法fun onMapReady(map: GoogleMap?)来设置一个类属性map

您有两个设计选项可供选择:

1)如果mapnull

,您的应用将无效
class A {
    lateinit var map: GoogleMap  // never ever `null`

    fun onMapReady(map: GoogleMap?) {
        map = map!!  // throws
    }

    fun onMapReady2(map: GoogleMap?) {
        map = map ?: throw Exception("in case you care for the exception")
    }
}

2)Null对你有特殊意义,可以:

class A {
    var map: GoogleMap? = null  // map is not ready yet

    fun onMapReady(map: GoogleMap?) {
        map = map
    }
}

当然,如果您的案例是案例(1)并且您可以控制API,那么您永远不应该有一个可以为空的接收者map: GoogleMap?,因为它会混淆该类的用户。

答案 2 :(得分:-1)

我看到两个不同的问题:
1.无效处理
2.用于空处理的Kotlin特定语法

首先不是kotlin特定的问题。这取决于,@ voddan几乎解释了可用的策略。

关于语法。 如果您只对非空值感兴趣,请使用let()

override fun onMapReady(map: GoogleMap?) {
        map?.let { m ->
            // do your staff 
            // 'm' now is definitely not null
        }
    }

如果您想知道它何时为空,请使用通常的if-else块

override fun onMapReady(map: GoogleMap?) {
    if (map != null) {
        this.map = map
    } else {
        Log.d("Activity","MapIsNull")
    }    

图片的标题说明:
1] @Cedric有关于kotlin的let()和朋友的nice post 2]结账@yole's comment。当在IDEA中重写乐趣时,可以将其标记为“?”,但实际上它们不是。