java - 取消引用可能会产生 'java.lang.NullPointerException'

标签 java android nullpointerexception

<分区>

以下代码 fragment 会在 Android Studio 中产生 lint 警告。

    Bundle extras = getIntent().getExtras();
    if (extras != null && extras.getString(REDIRECT_KEY) != null) {
        switch (extras.getString(REDIRECT_KEY)) { ... 

extras.getString(REDIRECT_KEY) 产生警告

enter image description here

Dereference of 'extras.getString(REDIRECT_KEY)' may produce 'java.lang.NullPointerException'

但我没有看到任何可能发生这种情况的情况。这是 lint 检查中的错误,它根本无法识别我之前在 if 中的空检查吗?还是我错过了什么?

编辑: 将代码更改为以下,确实删除了警告

if(getIntent() != null && getIntent().getStringExtra(REDIRECT_KEY) != null){
        switch (getIntent().getStringExtra(REDIRECT_KEY)){
            ...
        }
    }

但这只是因为这种方式而消失了,这个 lint 检查有效(至少我猜)。如果我向这张支票显示更多信息,它会在某一时刻说

Variables, method parameters and return values marked as @Nullable or @NotNull are treated as nullable (or not-null, respectively) and used during the analysis to check nullability contracts

查看Bundle和Intent的源码显示:

/**
 * Retrieve extended data from the intent.
 *
 * @param name The name of the desired item.
 *
 * @return the value of an item that previously added with putExtra()
 * or null if no String value was found.
 *
 * @see #putExtra(String, String)
 */
public String getStringExtra(String name) {
    return mExtras == null ? null : mExtras.getString(name);
}

和BaseBundle

/**
 * Returns the value associated with the given key, or null if
 * no mapping of the desired type exists for the given key or a null
 * value is explicitly associated with the key.
 *
 * @param key a String, or null
 * @return a String value, or null
 */
@Nullable
public String getString(@Nullable String key) {
    unparcel();
    final Object o = mMap.get(key);
    try {
        return (String) o;
    } catch (ClassCastException e) {
        typeWarning(key, o, "String", e);
        return null;
    }
}

如您所见,BaseBundle 将其返回值设置为@Nullable,而 Intent 则没有。所以使用 getStringExtra 只能消除症状,而不是原因。我仍然猜测这是由于 lint 检查不充分造成的,而不是我这边的错误编码。或者还有人看到可以抛出 Null 指针的场景吗?

最佳答案

看看这个取自 here 的例子

class Argument {

    public final static int TOMAYTO = 0;
    public final static int TOMAHTO = 1;

    static void argue() {

        int say = TOMAYTO;

        while (true) {

            switch (say) {

            case TOMAYTO:

                say = TOMAHTO;
                break;

            case TOMAHTO:

                say = TOMAYTO;
                break;
            }
        }
    }
}

javac 为 argue() 方法生成的字节码如下所示:

   0 iconst_0 // Push constant 0 (TOMAYTO)
   1 istore_0 // Pop into local var 0: int say = TOMAYTO;
   2 iload_0 // Push key for switch from local var 0
                          // Perform switch statement: switch (say) {...
                          // Low case value is 0, high case value is 1
                          // Default branch offset will goto 2
   3 tableswitch 0 to 1: default=2
            0: 24 // case 0 (TOMAYTO): goto 24
            1: 29 // case 1 (TOMAHTO): goto 29

                          // Note that the next instruction starts at address 24,
                          // which means that the tableswitch took up 21 bytes
  24 iconst_1 // Push constant 1 (TOMAHTO)
  25 istore_0 // Pop into local var 0: say = TOMAHTO
  26 goto 2 // Branch unconditionally to 2, top of while loop
  29 iconst_0 // Push constant 1 (TOMAYTO)
  30 istore_0 // Pop into local var 0: say = TOMAYTO
  31 goto 2 // Branch unconditionally to 2, top of while loop

正如您所看到的,对于具有 String 数据类型的 switch 语句,完成了一个表切换,并且对于每种情况,传递给 switch 的值都会与案例的值进行比较,所以这意味着在您的案例中 extras.getString 可以被多次调用,而无需调用之前的 if 检查,因此,由于 extras 是一个包,它有可能被取消引用并导致空指针异常。

创建局部变量而不是多次调用该方法始终是一个好习惯,您可以查看 this presentation by Jake Wharton了解原因。

关于java - 取消引用可能会产生 'java.lang.NullPointerException',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35600518/

相关文章:

Java Split() 函数给出空指针异常错误

java - NullPointerException 仅适用于某些设备上的动画

java - Struts 在页面加载时调用操作

java - Python:可以将文本发送到已经运行的java应用程序的标准输入吗?

android - 在 ActionBarSherlock 上显示自定义按钮以显示滑动菜单

Android Studio 3.5 - 格式化 (ctrl+Alt+L) XML 文件中的代码正在重新排列 LinearLayout 中的 View

javascript - 带有 Firebase 云消息传递的 Android WebView

javascript - 无法写入 asp.net 中的脚本标记

java - toString() 是否定义为为 java.lang.String 返回 this?

java - Eclipse 中 Tomcat 上 Jersey 的基本完整配置