Java 防止NullPointerException警告的最佳方法?

Java 防止NullPointerException警告的最佳方法?,java,android-studio,nullpointerexception,Java,Android Studio,Nullpointerexception,我在Android studio中收到了这样一条警告,它告诉我: 方法调用'data.getExtras().get(“address”).toString()'可能会产生'java.lang.NullPointerException' 所以我改变了我的代码来摆脱那个警告 // Function to read the result from newly created activity @Override protected void onActivityResult(int requestC

我在Android studio中收到了这样一条警告,它告诉我:

方法调用'data.getExtras().get(“address”).toString()'可能会产生'java.lang.NullPointerException'

所以我改变了我的代码来摆脱那个警告

// Function to read the result from newly created activity
@Override
protected void onActivityResult(int requestCode,
                                int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == 100 && data.getExtras().get("x") != null &&
            data.getExtras().get("y") != null && data.getExtras().get("address") != null) {
        String sX = data.getExtras().get("x").toString();
        String sY = data.getExtras().get("y").toString();
        String sAddress = data.getExtras().get("address").toString();
        double dX = Double.parseDouble(sX);
        double dY = Double.parseDouble(sY);
        ShowSearch(dX, dY, sAddress);
    }
    else{
        Log.d("onActivityResult()", "Something went wrong, either the result code is wrong or the data is null");
    }
}
然后经过再三考虑,我选择了试一试

// Function to read the result from newly created activity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == 100) {
        try {
            String sX = data.getExtras().get("x").toString();
            String sY = data.getExtras().get("y").toString();
            String sAddress = data.getExtras().get("address").toString();
            double dX = Double.parseDouble(sX);
            double dY = Double.parseDouble(sY);
            ShowSearch(dX, dY, sAddress);
        } catch (java.lang.NullPointerException e){
            Log.d("onActivityResult()", "Something went wrong, some data is null");
        }
    }
}
但是使用try-catch会在androidstudio中带回警告,而我很确定它不应该出现,因为不管它是否为null,我现在正在处理它

我的问题是,这两个解决方案中哪一个在技术上更有效,如果是try-catch解决方案,为什么Android Studio总是给我一个警告

(Android Studio 2.1.1)

更新:在尝试了多种解决方案后,我意识到android studio即使在第一个示例中也给了我一个警告,所以我仍然有这个警告,但它不再困扰我了

对于那些感兴趣的人,这里是我决定使用的新解决方案:(我仍然收到警告)


您不应该捕获
NullPointerException
——事实上,应该捕获的
RuntimeException
很少

NullPointerException
表示代码存在问题,其中在方法上调用变量(或访问其字段),而引用实际具有
null

这本质上要求检查
null

这就是Android Studio在这种情况下似乎学究式地积极主动的地方:当然,您可以通过链接对象上的方法调用来获得NPE,如果您不能保证对象将
null
,您应该检查
null

例如:

if (resultCode == 100 
    && data.getExtras().get("x") != null 
    && data.getExtras().get("y") != null 
    && data.getExtras().get("address") != null) { ...
。。。会变成,乏味地:

if (resultCode == 100 
    && data != null // unlikely
    && data.getExtras() != null
    && data.getExtras().get("x") != null 
    ...
。。。或者更确切地说,在这种情况下:

if (resultCode == 100 
    && data != null // unlikely
    && data.hasExtra("x")
    ...
这种更改很乏味,而且会增加混乱,但只要您的方法调用没有改变任何对象(否则,只需在检查
null
值之前指定一个变量),就不会影响性能

似乎有一些方法可以根据您从IDE得到的警告参数化Android Studio

请参见问题了解大致方向

注释/后期编辑

因为这是一个古老的答案,一个关于Java8的词

  • 可选
    s旨在传达可能存在或不存在的数据的概念,例如引用对象的实例
  • 换句话说,
    Optional
    T
    实例的容器,我们不确定该实例是否存在
  • Optional
    类提供了许多方法来处理这种不确定性,比繁琐地执行
    null
    检查要优雅得多,有些人可能会争辩说,这比一开始就必须处理指针的概念要优雅得多,由可怕的
    Null
    指针
    异常
    s传达
  • Optional
    s在Java8的流中大量使用
  • 最后,从Oracle自己的角度来看,这是一个关于
    Optional
    s的良好起点

    • 我认为这更适合您的要求。如果您只是记录异常,那么抛出异常的代价很高

      VariableType extrasX = data.getExtras();
      VariableType extrasY = data.getExtras();
      VariableType addressS= data.getExtras();
      
      if(extrasX !=null && extraYs != null && addressS != null){
      
          VariableType xType = extrasX.get("X");
          VariableType yType = extrasY.get("Y");
          VariableType addressType = addressS.get("address");
      
          if(xType !=null && yType != null && addressType != null){
      
                  String sX = xType.toString();
                  String sY = yType.toString();
                  String sAddress = addressType.toString();
                  double dX = Double.parseDouble(sX);
                  double dY = Double.parseDouble(sY);
                  ShowSearch(dX, dY, sAddress);
      
          } else {
              Log.d("onActivityResult()", "Something went wrong, some data is 
          }
      } else {
          Log.d("onActivityResult()", "Something went wrong, some data is 
      }
      

      通常,抛出异常是为了避免在不同条件下出现意外的编程错误或失败。另外,在某些情况下抛出异常可能代价高昂,所以我肯定会使用空检查(如果可能的话)


      有关更多详细信息。

      涉及
      可选对象的公认答案要求API级别为24或更高,因此我通常使用Android Studio建议在突出显示的对象周围插入
      对象。requirennoull()

      • 它消除了警告
      • 它留下了失败的可能性,即出现
        NullPointerException
        (这将导致更好的代码)
      • 它的Android API级别低于
        可选
      • 它比
        Optional
        所需的详细得多
      因此,与其检查
      data.getExtras().get(“x”)!=null
      并忽略它为null时的潜在问题,最好使用

      Objects.requirennoull(data.getExtras().get(“x”))

      直接在代码中


      当然,在某些情况下,您可以将其设置为
      null
      ,在这种情况下,
      data.getExtras().get(“x”)!=空
      检查很好,导致代码忽略动作,当它是空的时候,我会相应地进行编辑。“为什么Android Studio总是在try-catch代码上给我一个警告”我能看到的唯一答案是:Android Studio没有对代码进行足够的内省来知道你正在处理它;或者说,设计预警系统的人根本不在乎你是否能处理好它。在效率方面:它起作用的几率非常、非常、非常、非常低。从维护的角度来看,做你觉得最清晰和干净的事情。在您的第一个示例中,任何合适的JIT都会很好地优化空检查(我不知道Dalvik的JIT有多好)。不确定哪一个更有效,但我不会捕获NullPointerException。当抛出NullPointerException时,应该是程序员的错误。作为一名程序员,我们确保他们不会被抛出(通过空检查)。不确定这是我个人的喜好还是被其他人广泛接受,但我个人认为捕获NullPointerException是一种不好的做法,应该尽可能避免。仍然有一些未检查的内容:
      getExtras()
      可以返回
      null
      。使用
      Intent#hasExtra(字符串名)
      可以解决这个问题,idk,如果nullcheck知道的话。谢谢你提供了信息丰富的答案,我从来没有意识到用这种方式使用try-catch的缺点。然而,看看您的代码示例,检查“data!=null”不是多余的吗?检查“data.ge”不是很好吗
      VariableType extrasX = data.getExtras();
      VariableType extrasY = data.getExtras();
      VariableType addressS= data.getExtras();
      
      if(extrasX !=null && extraYs != null && addressS != null){
      
          VariableType xType = extrasX.get("X");
          VariableType yType = extrasY.get("Y");
          VariableType addressType = addressS.get("address");
      
          if(xType !=null && yType != null && addressType != null){
      
                  String sX = xType.toString();
                  String sY = yType.toString();
                  String sAddress = addressType.toString();
                  double dX = Double.parseDouble(sX);
                  double dY = Double.parseDouble(sY);
                  ShowSearch(dX, dY, sAddress);
      
          } else {
              Log.d("onActivityResult()", "Something went wrong, some data is 
          }
      } else {
          Log.d("onActivityResult()", "Something went wrong, some data is 
      }