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

时间:2016-05-17 14:13:53

标签: java android-studio nullpointerexception

我在Android工作室发出了这个警告,告诉我:

  

方法调用' 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会在android-studio中收回警告,我现在正在处理它。

这是我的问题,如果它是尝试捕获解决方案,那么两个解决方案中的哪一个在技术上更有效率,为什么Android Studio会不断给我一个警告?

(Android Studio 2.1.1)

更新:在尝试了多个解决方案之后,我意识到Android工作室甚至在第一个例子中给了我一个警告,所以我仍然有警告,但它不再困扰我了。

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

// 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 != null) {
        if (data.hasExtra("x") && data.hasExtra("y")
                && data.hasExtra("address")) {
            if (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 {
                Toast.makeText(this, "Error in location", Toast.LENGTH_SHORT).show();
                Log.d("onActivityResult()", "Something went wrong, some extra data is null");
            }
        } else {
            Toast.makeText(this, "Error in location", Toast.LENGTH_SHORT).show();
            Log.d("onActivityResult()", "Something went wrong, some extra data doesn't exist");
        }
    } else{
        Toast.makeText(this, "No Location found", Toast.LENGTH_SHORT).show();
        Log.d("onActivityResult()", "Something went wrong, either the result code is wrong or the data is null");
    }
}

4 个答案:

答案 0 :(得分:7)

你不应该抓住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。

有关总体方向,请参阅this问题。

注意/延迟编辑

这是一个古老的答案,关于Java 8的Optional

  • Optional旨在传达可能存在或不存在的数据概念,例如引用对象的实例。
  • 换句话说,Optional<T>T实例的容器,其存在我们不确定。
  • Optional类提供了许多方法来处理这种不确定性 lot 比不必繁琐地执行null检查更有优雅,或者有些人可能会说,而不是首先处理指针的概念,正如可怕的Null 指针 Exception所传达的那样。
  • Optional大量使用在Java 8的流API中。
  • 最后,here从甲骨文自己的角度来看是Optional的一个很好的起点。

答案 1 :(得分:1)

通常会抛出异常,以避免意外编程错误或在不同条件下出现故障。另外,在某些情况下抛出异常会很昂贵,所以我肯定会使用空值检查(如果可能的话)。

Check also this question了解更多详情。

答案 2 :(得分:0)

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

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 
}

答案 3 :(得分:0)

可接受的涉及Optional对象的答案要求API级别为24或更高,因此我通常会推荐Android Studio建议在突出显示的对象周围插入Objects.requireNonNull()

  • 它消除了警告
  • 这可能会导致NullPointerException失败(从而导致更好的代码)
  • Optional相比,它可用于更低的Android API级别
  • 它比Optional所需要的冗长得多。

因此,与其检查data.getExtras().get("x") != null并忽略它为null时的潜在问题,不如使用它

  

Objects.requireNonNull(data.getExtras().get("x"))

直接在您的代码中。

当然,在某些情况下,如果您对null感到满意,则在这种情况下,data.getExtras().get("x") != null检查很好,导致代码在{{1}时忽略该操作}。