項目實戰:借鑑Android API源碼(Splitter-split和TextView-setText),不懼NullPointerException(文末彩蛋)

NullPointerException空指針異常可以說是我們開發中最常遇到的Bug,因此我們處處判空,膽戰心驚。

處處判空確實可以解決空指針異常的Crash。

但處處判空未免過於草木皆兵,而且寫出來的代碼十分不優雅,多餘判斷效率低下,這不是我們的Style!

這裏,我們由點到面,借鑑一下Android API中Splitter類的split方法和TextView類的setText方法,我們不懼NullPointerException!

先看一下這幾行項目源代碼:

        String[] paraString = logPara.split("\\*");
        viewHolder.time_tv_networkPara.setText(paraString[0]);
        viewHolder.key_tv_networkPara.setText(paraString[1]);
        viewHolder.value_tv_networkPara.setText(paraString[2]);

我們不管它的業務意義,簡單來說就是通過*分割字符串logPara,然後通過TextView顯示出來。

這時,有小夥伴可能會說,如果分割出來爲空,然後setText空,那不就空指針異常了嗎,嚇死寶寶了,趕緊判個空先。

首先,表揚這位小夥伴的風險意識,防患於未然哈,

然而,真的需要在這判空嗎?

此時我抽出一個小Demo,我們一步步分析。

正常情況:

	private static final String test1 = "2017-02-06 14:25:59:939*/resxxx/xx/xxx/xxxx/xxxOrder/xxxlist*{'xxxId':'0','isXXXX':'0','xxxFlag':0}";
	
	public static void main(String[] args) {
        String[] paraString = test1.split("\\*");
        System.out.println(paraString[0]);
        System.out.println(paraString[1]);
        System.out.println(paraString[2]);
	}

輸出:

2017-02-06 14:25:59:939
/resxxx/xx/xxx/xxxx/xxxOrder/xxxlist
{'xxxId':'0','isXXXX':'0','xxxFlag':0}

理想結果,ok~


那麼我們測一把爲空情況呢?

private static final String test2 = "2017-02-06 14:25:59:939**{'xxxId':'0','isXXXX':'0','xxxFlag':0}";

        String[] paraString = test2.split("\\*");
        System.out.println(paraString[0]);
        System.out.println(paraString[1]);
        System.out.println(paraString[1] == null);
        System.out.println(paraString[1].equals(""));
        System.out.println(paraString[2]);

輸出:

2017-02-06 14:25:59:939

false
true
{'xxxId':'0','isXXXX':'0','xxxFlag':0}
此時paraString[1]值爲"",但並不爲空,因此不存在分割出來爲空的情況,最多隻是""。不用判空!

在這裏我們可以追一下Android API源代碼,打破砂鍋問到底,知道原理方能決定是否判空,從而遊刃有餘。

從Sting:

    public String[] split(String regularExpression, int limit) {
        String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit);
        return result != null ? result : Pattern.compile(regularExpression).split(this, limit);
    }

到Pattern:

    public String[] split(CharSequence input, int limit) {
        return Splitter.split(this, pattern, input.toString(), limit);
    }

再到Splitter:

AndroidSDK/sources/android-23/java/util/regex/Splitter.java

    public static String[] split(Pattern pattern, String re, String input, int limit) {
        String[] fastResult = fastSplit(re, input, limit);
        if (fastResult != null) {
            return fastResult;
        }

        // Unlike Perl, which considers the result of splitting the empty string to be the empty
        // array, Java returns an array containing the empty string.
        if (input.isEmpty()) {
            return new String[] { "" };
        }
···

如果爲空,則返回一個array,array裏有一個空字符串。因此分割出來不會爲空,自然不需要判空。

退一步來說,如果遇到其他case,字符串爲空,我們setText一個空字符串時是否會有問題呢?

同樣,在這裏我們追一下Android API源代碼,打破砂鍋問到底,知道原理方能決定是否判空,從而遊刃有餘。

AndroidSDK/sources/android-23/android/widget/TextView.java

setText(CharSequence text)

->setText(CharSequence text, BufferType type)

->setText(CharSequence text, BufferType type,boolean notifyBefore, int oldlen)

        if (text == null) {
            text = "";
        }

至此,真相大白,如果爲空,賦值"",不用判空。


小結ing:

1.追溯Android API,打破砂鍋問到底,知道原理方能決定是否判空,從而遊刃有餘,不懼NullPointerException,寫出更加優雅的代碼。

2.借鑑Android API(Splitter-split和TextView-setText),處理各種case,寫出更加健壯的代碼。


文末彩蛋:

看到這,小小的過癮一把,

追加更加優雅,更加健壯的代碼是我們不變的信念。


然而,話說回來,有沒有覺得什麼地方不對勁?

別往下看,先自己沉思三分鐘,什麼?沒啥不對勁?

回過頭從頭看一遍,什麼?挺好的?

哈哈,前面說的是不錯,不過有一個問題。

這裏確實沒有空指針異常,也不需要判空,但是:

添加代碼:

System.out.println(paraString[3]);

可能會碰到另一個我們時不時遇見的Bug,

數組越界:java.lang.ArrayIndexOutOfBoundsException

這裏就根據自己的業務需求個人處理了~


權興權意-品質爲真

原創不易,轉載請註明出處哈。

http://blog.csdn.net/hxqneuq2012/article/details/54892425

發佈了166 篇原創文章 · 獲贊 16 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章