Alb*_*tNf 7 java android nullpointerexception
以下代码段在Android Studio中生成lint警告.
Bundle extras = getIntent().getExtras();
if (extras != null && extras.getString(REDIRECT_KEY) != null) {
switch (extras.getString(REDIRECT_KEY)) { ...
Run Code Online (Sandbox Code Playgroud)
extras.getString(REDIRECT_KEY) 发出警告
取消引用'extras.getString(REDIRECT_KEY)'可能会产生'java.lang.NullPointerException'
但我没有看到任何可能发生这种情况的情况.它是lint检查中的一个错误,它只是不能识别我之前的if中的空检查吗?或者我会错过什么?
编辑:将代码更改为以下,确实删除了警告
if(getIntent() != null && getIntent().getStringExtra(REDIRECT_KEY) != null){
switch (getIntent().getStringExtra(REDIRECT_KEY)){
...
}
}
Run Code Online (Sandbox Code Playgroud)
但这只是因为方式,这种棉绒检查工作(至少我猜).如果我在这张支票上显示更多信息,它会在某一时刻说出来
标记为@Nullable或@NotNull的变量,方法参数和返回值被视为可空(或分别为非空),并在分析期间用于检查可空性合同
查看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);
}
Run Code Online (Sandbox Code Playgroud)
和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;
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,BaseBundle将其返回值设置为@Nullable,而Intent则不设置.所以使用getStringExtra只删除symoptoms,而不是原因.我仍然认为这是由于皮棉检查不足造成的,而不是我身边的错误编码.或者是否有人仍然看到一个可以抛出Null指针的场景?
看看从这里获取的这个例子
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
javac为argument()方法生成的字节码如下所示:
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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,对于具有 String 数据类型的 switch 语句,完成了 tableswitch,并且对于每种情况,传递给 switch 的值都会与该情况的值进行比较,因此这意味着在您的情况下extras.getString可以多次调用而无需之前的if检查被调用,因此由于 extras 是一个包,因此它有可能被取消引用并导致空指针异常。
创建局部变量而不是多次调用该方法始终是一个好习惯,您可以查看Jake Wharton 的演示文稿以了解原因。