- 在開發(fā)測(cè)試的過程中,發(fā)現(xiàn)一個(gè)崩潰,具體堆棧如下:
Process: xxx.xxx.xxx, PID: 27468
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.hashCode()' on a null object reference
at xxx.xxx.xxx.xxx.MessageFragment.getSexType(MessageFragment.java:57)
at xxx.xxx.xxx.xxx.MessageFragment.access$100(MessageFragment.java:22)
at xxx.xxx.xxx.xxx.MessageFragment$1.onClick(MessageFragment.java:50)
at android.view.View.performClick(View.java:7514)
at android.view.View.performClickInternal(View.java:7491)
at android.view.View.access$3600(View.java:846)
at android.view.View$PerformClick.run(View.java:28733)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8134)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
- 發(fā)現(xiàn) MessageFragment 類中的 57 行是一個(gè) String 調(diào)用
hashCode
的時(shí)候報(bào)空指針了,我回去看了一眼代碼
這個(gè)類 57 行中壓根沒有調(diào)用過 hashCode?看完我頓時(shí)陷入了沉思
過了一會(huì)兒我的小腦袋瓜靈機(jī)一動(dòng),是不是
getSexType
的sexString
參數(shù)為空導(dǎo)致的?但是如果sexString
參數(shù)為空,應(yīng)該走default
語句才對(duì)啊?怎么可能會(huì)調(diào)用hashCode
方法呢?更別說報(bào)空指針異常了?先不管它三七二十八,我先試驗(yàn)一下,實(shí)踐出真理。
于是乎,我將這個(gè)方法的參數(shù)直接改成了
null
,結(jié)果一運(yùn)行就真的復(fù)現(xiàn)了這個(gè)問題那么問題來了,我明明沒調(diào)用
hashCode
方法,為什么它就是提示我有呢?
既然能復(fù)現(xiàn),那么應(yīng)該從哪里從手這個(gè)問題?我的小腦瓜又靈機(jī)一動(dòng),是不是編譯器在編譯的過程中修改了我的代碼?我心想這種事情不太可能發(fā)生,但是實(shí)踐出真理,先試了再說
說干就干,我們都知道 apk 的類都是在 dex 文件里面的,而 dex 是由多個(gè) class 類合并而成,那么現(xiàn)在就讓我們?cè)陧?xiàng)目中的 build 文件夾中搜索剛剛出現(xiàn)崩潰的那個(gè)類
- 并把它拖動(dòng)到 Android Studio 打開看看看
結(jié)果真的被我猜對(duì)了,此時(shí)此刻我的心情是五味雜陳,沉思許久后發(fā)出了感嘆:居然還能這么玩,這波操作真是讓我開了眼
原來 Java JDK 1.8 支持
switch
判斷 String 類型是這么來的,本質(zhì)上還是走的switch
判斷 int 類型的邏輯,調(diào)用hashCode
方法只不過想得出字符串的哈希碼,而字符串的哈希碼是通過將 String 分解成一個(gè)個(gè)char
,然后通過運(yùn)算得出,所以相同內(nèi)容的 String 對(duì)象的hasCode
是一樣的。
既然知道了這其中的原理,那么剛剛的崩潰問題要怎么處理比較好?我認(rèn)為有兩種方式
第一種:用 String 作為
switch
的判斷條件時(shí),應(yīng)當(dāng)先進(jìn)行判空
private int getSexType(String sexString) {
if (sexString == null) {
return 0;
}
int sexType = 0;
switch (sexString) {
case "男":
sexType = 0;
break;
case "女":
sexType = 1;
break;
default:
break;
}
return sexType;
}
- 第二種:可以換成
if else
+equals
語句來判斷
private int getSexType(String sexString) {
if ("男".equals(sexString)) {
return 0;
} else if ("女".equals(sexString)) {
return 1;
}
return 0;
}
- 至于用哪一種,這里不做強(qiáng)制要求,大家可以看著來