Java 在不使用null的情况下编写代码

Java 在不使用null的情况下编写代码,java,android,Java,Android,在Java中,对象默认初始化为null 我最近在研究如何正确处理NPE时发现了这个答案: 以下是我在这篇文章中的主要观点: 如果从未将变量设置为null,则永远不会出现意外的null 不允许空参数 我一直想知道如何在Java和Android中处理这个问题。我在开发者面板上看到的许多崩溃报告都是NPE,我注意到在我的代码中,我使用null检查是否可以继续操作 我正在梳理我的代码库,试图尽可能地删除null和默认实例化,但我遇到了一些似乎不可能做到的地方,我不确定如何修复这些变量引起的错误 例如,在

在Java中,对象默认初始化为
null

我最近在研究如何正确处理NPE时发现了这个答案:

以下是我在这篇文章中的主要观点:

如果从未将变量设置为null,则永远不会出现意外的null

不允许空参数

我一直想知道如何在Java和Android中处理这个问题。我在开发者面板上看到的许多崩溃报告都是NPE,我注意到在我的代码中,我使用
null
检查是否可以继续操作

我正在梳理我的代码库,试图尽可能地删除
null
和默认实例化,但我遇到了一些似乎不可能做到的地方,我不确定如何修复这些变量引起的错误

例如,在使用Google Maps API时,必须声明一个
GoogleMap
对象。我当前设置它的方式是将变量声明为我的
活动的成员,然后在
onCreate()
期间初始化它。不幸的是,在
onResume()
期间,当我在
GoogleMap
上调用
.clear()
时,该字段偶尔会
null
。我无法在自己的环境中重现这个错误,这导致我在处理NPE时做了更多的阅读

在这里的另一个(非常流行的)问题中,最重要的和公认的答案建议了解决这个问题的三种策略

  • assert
    语句。从表面上看,这更像是单元测试/调试代码,特别是因为Java默认忽略了
    assert
  • 空对象模式。这可能是最具吸引力的解决方案,因为它最终看起来和感觉更干净。但是,当使用外部库时,我不确定这是否是一个选项。扩展外部库似乎很混乱
  • 试一试。这很难。由于
    null
    在Java中非常普遍,因此代码最终会充斥着try/catch,用于查找可能为null的所有内容,或者最终会阻塞大量的代码,这样在捕获错误时就无法精确地处理后果
  • 我的问题是,还有其他选择吗?也许我可以使用一种编码模式,或者某种内置的方法来解决这个问题

    最理想的情况是,我想要一个不会崩溃、丢失数据可靠性或丢失应用程序功能的解决方案


    注意-这不是关于我的代码问题的问题,这是关于如何在默认初始化为
    null

    的语言中防御性地编写代码以防止意外的NPE的问题,我真的不明白为什么null检查被认为是不好的,至于防止顶级异常使用
    @NonNull
    @Nullable
    注释,静态分析确实有帮助。

    我发现引用文章的前提存在异常。它说:

    当抛出
    NullPointerException
    时,错误不在范围内,错误在代码的前面,在代码中,变量被设置为
    null
    ,而您并不期望它是

    我想说的是,这个bug是因为您不希望值为
    null
    ,所以这个bug正好是NPE发生的地方

    和其他工具一样,最重要的是如何使用它。使用
    null
    值指示没有值是完全正确的,只要定义良好

    这就是说,
    null
    确实被过度使用了,有时应该用异常替换。但这完全取决于环境


    看看Java中的接口。要从队列中删除值,可以调用
    remove()
    ,该函数在队列为空时引发异常,也可以调用
    poll()
    ,该函数返回
    null
    。如果需要一个值,请使用
    remove()
    。如果您知道队列可能为空,并且您将处理该问题,请使用
    poll()
    。不要将
    remove()
    与try-catch一起用于流控制。

    我问了自己同样的问题,最后抛出异常并将其缓存在代码的顶层。这样做,我只需要在没有条件的情况下声明try-catch一次。当然,它需要确保如果某些值预期不存在或无效,则抛出异常:

        bool isEquals(string name)
        {
          if(tempData == name.toUpperCase()) // if name is null,a null reference will be throw
    
           //...
        }
    

    即使你没有摆脱NPE和try/catch,你也可以确信应用程序在哪里失败了,这是一个很大的优点。

    Null本身是无法避免的。任何尚未分配并成功编译的已声明引用在Java中都被视为null,原因很好:堆上有垃圾值。Java跟踪您的分配,并在仍包含应用程序分配该堆块时的垃圾值的内存位置上返回null。它阻止你获取整数之类的值,以为它们属于你,而实际上它们是在你的应用程序启动之前使用同一地址的其他应用程序遗留下来的

    列出的每一种策略都有自己的用途,没有一种是处理可能的NPE的通用策略

    断言通常是需要避免的。如果不满足条件,它将导致一个halt语句。换句话说,这不是一个优雅的出口。A=null语句实现了与assert相同的目标,但具有响应条件而不是停止程序的选项

    try/catch在您可能遇到比赛条件的情况下非常强大。这在调用异步库和大量使用网络相关操作的库时特别有用。GoogleMaps有许多方法可以根据新的位置或视图框获取更新的信息,在某些情况下,您可能会尝试对受b管理的对象进行调用