簡體   English   中英

在預期時處理NumberFormatException的正確方法是什么?

[英]What is the proper way to handle a NumberFormatException when it is expected?

我遇到了這種情況,我需要將一個String解析為一個int ,我不知道如何處理NumberFormatException 當我沒有抓住它時,編譯器不會抱怨,但我只是想確保我正確處理這種情況。

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
    }
    return i;
}

我想簡化這樣的代碼。 編譯器沒有問題,但線程在NumberFormatException上消失。

private int getCurrentPieceAsInt() {
    int i = 0;
    i = Integer.parseInt(this.getCurrentPiece());
    return i;
}

Google CodePro希望我以某種方式記錄異常,我同意這是最佳做法。

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        i = 0;
        e.printStackTrace();
    }
    return i;
}

我希望此方法在當前片段不是數字或無法解析時返回0 當我沒有明確捕獲NumberFormatException ,它是否不分配變量i 或者是否有一些Integer.parseInt()返回的默認值?

一般風格說,如果我捕獲異常,我應該在某處記錄它。 我不想記錄它。 這個異常有時被拋出是正常的操作,這對我來說也不合適。 但是,我找不到一個函數,它會告訴我Integer.parseInt()是否會拋出異常。 所以我唯一的行動方式似乎就是調用它並捕獲異常。

parseIntjavadoc沒有多大幫助。

以下是我想知道的具體問題:

  • 有沒有我可以調用的方法,它會告訴我Integer.parseInt()在調用之前是否會拋出NumberFormatException 然后我就沒有問題記錄這個,因為它永遠不會發生。
  • 如果我只是沒有捕獲異常,那么valiable會不會被分配? 然后我會簡單地將它初始化為我想要的值,當它不是數字而不是捕獲異常時。
  • 有沒有辦法明確標記異常,我不關心它? 我認為這將類似於AWTEvent.consume() 如果是這樣,那么我會這樣做,以便Google CodePro不會將其視為“未記錄”。
  • 有沒有我可以調用的方法,它會告訴我Integer.parseInt()在調用之前是否會拋出NumberFormatException? 然后我就沒有問題記錄這個,因為它永遠不會發生。

可悲的是沒有。 至少不在核心Java API中。 然而,編寫一個很容易 - 只需修改下面的代碼即可。

  • 如果我只是沒有捕獲異常,那么valiable會不會被分配? 然后我會簡單地將它初始化為我想要的值,當它不是數字而不是捕獲異常時。

如果你沒有捕獲異常,那么堆棧將展開,直到它遇到將處理它的catch塊,或者它將完全展開並停止線程。 事實上,變量不會被分配,但這並不是你想要的。

  • 有沒有辦法明確標記異常,我不關心它? 我認為這將類似於AWTEvent.consume()。 如果是這樣,那么我會這樣做,以便Google CodePro不會將其視為“未記錄”。

可能有一種方法可以告訴CodePro忽略此特定警告。 當然,使用FindBugs和Checkstyle等工具,您可以關閉特定位置的警告。 (編輯:@Andy指出了如何做到這一點。)

我懷疑你想要的是@daveb提到的Commons lang包。 編寫這樣的函數非常容易:

int parseWithDefault(String s, int def) {
    try {
        return Integer.parseInt(s);
    }
    catch (NumberFormatException e) {
        // It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input.
        return def;
    }
}

commons lang中NumberUtils.toInt(String,int) ,它可以完全按照你的意願行事

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42
* Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".

是的,您可以在本地禁用一行代碼的CodePro審核規則:

http://code.google.com/javadevtools/codepro/doc/features/audit/locally_disabling_audit_rules.html

也就是說,不一定要在每個異常catch塊中包含診斷日志記錄。 有時,最好的方法是采取默認課程。 有時它是與用戶交互的。 這取決於。

為現在和將來的使用創建自己的便利方法:

public static int parseInt(final /*@Nullable*/ String s, final int valueIfInvalid) {
    try {
        if (s == null) {
            return valueIfInvalid;
        } else {
            return Integer.parseInt(s);
        }
    } catch (final NumberFormatException ex) {
        return valueIfInvalid;
    }
}

有沒有我可以調用的方法,它會告訴我Integer.parseInt()在調用之前是否會拋出NumberFormatException? 然后我就沒有問題記錄這個,因為它永遠不會發生。

不是我知道的。 請記住,如果有,您可能最終解析該值兩次(一次驗證,一次解析)。 我理解你想要避免異常,但在這種情況下,這是捕獲異常是Java中的標准習語,它不提供另一個(至少我知道)。

如果我只是沒有捕獲異常,那么valiable會不會被分配? 然后我會簡單地將它初始化為我想要的值,當它不是數字而不是捕獲異常時。

你必須捕獲異常(即使它什么都不做),否則它將逃脫阻塞並向上拋出堆棧。

有沒有辦法明確標記異常,我不關心它? 我認為這將類似於AWTEvent.consume()。 如果是這樣,那么我會這樣做,以便Google CodePro不會將其視為“未記錄”。

我不知道。 我會使用上面的便捷方法(我在我的所有項目中使用的一小部分通用實用程序中都有類似的東西)。

如果你正在處理它的真正正常情況,我不會記錄它。 我不是谷歌CodePro的家庭,但我希望有一種方法來抑制警告,例如某種@SuppressWarnings(“xxx”)注釋/關鍵字。


編輯:我想在下面的評論中指出這些評論

這種方法仍然沒有處理異常。 捕獲異常並對其執行任何操作都是不好的形式。 這就是為什么我在尋找更好的解決方案

...通過返回指示的valueIfInvalid 來處理異常(情況)。 “糟糕的形式”你指的是盲目地,不假思索地寫空陷阱不良做法,從不回過頭來真正考慮並解決這個問題。 如果考慮異常情況並且對情況做了正確的事情即使正確的事情是什么都不做 ),那么你已經“處理”了異常

正如其他人所提到的,沒有可以調用來驗證整數的內置核心Java API方法,但是您可以使用Character類來驗證輸入而不使用異常處理。 例如:

package com.example.parseint;

public class ValidateIntExample {
    public static boolean isInteger(String s) {
        if (s == null) {
            return false;
        }

        s = s.trim();

        if (s.length() == 0) {
            return false;
        }

        int start = 0;
        if (s.charAt(0) == '-') { // handle negative numbers
            if (s.length() == 1) {
                return false;
            }
            else {
                start = 1;
            }
        }

        for (int i = start; i < s.length(); i++) {
            if (! Character.isDigit(s.charAt(i))) {
                return false;
            }
        }

        return true;
    }
}

實際上, parseInt本身在內部使用Character.isDigit ,您可以在JRE源代碼中驗證它。 (對不起,我會在這里包含parseInt方法,但我不確定我是否允許根據許可條款。)如果你正在使用Eclipse並且你的項目附有JRE源代碼,那么你就可以了- 在代碼中單擊Integer.parseInt方法,然后單擊“打開聲明”。

你應該像正在做的那樣捕捉異常。 這很煩人,但最好的辦法。

當字符串不是有效的int時,沒有Java API方法將返回0。

當字符串不是int時,將拋出異常,因此除非您按原樣捕獲異常,否則不會設置int變量。

你的第一個代碼塊是正確的。 當發生異常並且您必須捕獲該異常時, i不會被隱式轉換為0。 catch內設置i為0是正確的; 雖然你可以簡單地取代i = 0; return 0; 在這種情況下,您無法避免異常處理。

為了澄清,你可以使用這個:

private int getCurrentPieceAsInt() {
    int i = 0;
    try {
        i = Integer.parseInt(this.getCurrentPiece());
    } catch (NumberFormatException e) {
        // log that an exception occured if it's needed
        return 0;
    }
    return i;
}

如果不清楚你應該如何從getter處理它,你就不應該抓住它並讓調用者處理它。 如果你知道應該如何處理它,你應該這樣做。 在這種情況下,記錄它可能不是必需的或非常有用。

如果您不知道如何處理異常並且將其留給閱讀日志的人,則記錄異常會更有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM