簡體   English   中英

在 Java 8 中沒有 try-catch 的 parseInt 方法?

[英]Way to parseInt without try-catch in Java 8?

有沒有更好的方法來嘗試將一個可以是或不是整數的字符串轉換為 int ? Integer.parseInt(String value) 將適用於“25”或“019”,但不適用於“hello”或“8A”。 在 Java 8 中,我們有可選值,例如:

public static void main(String[] args) {
    Optional<Integer> optionalResult = functionThatReturnsOptionalInteger();
    Integer finalValue = optionalResult.orElse(0);
    System.out.println(finalValue);
}

public static Optional<Integer> functionThatReturnsOptionalInteger() {
    Integer[] ints = new Integer[0];
    return Stream.of(ints).findAny();
}

您不需要檢查空值,因為Optional包裝器公開了處理這種情況的有用方法。

但是如果你想parseInt一個字符串,它可以是空的,或者不包含一個有效的整數,解決方案和往常一樣:

public static Integer parseIntOrDefault(String toParse, int defaultValue) {
    try {
        return Integer.parseInt(toParse);
    } catch (NumberFormatException e) {
        return defaultValue;
    }
}

如何使用 Java 8 功能改進這一點,為什么 Integer.parseInt() 沒有被重載以在參數錯誤的情況下返回 Optional (或者只是添加一個新方法 Integer.parseIntOptional() 到 Integer 包裝器)

標准庫 afaik 中不存在這樣的東西,但是您可以編寫一個方法,將String解析為Optional<Integer>如下所示:

public static Optional<Integer> parseInt(String toParse) {
    try {
        return Optional.of(Integer.parseInt(toParse));
    } catch (NumberFormatException e) {
        return Optional.empty();
    }
}

現在已刪除的其他答案不同,我不認為這真的與 Java 向后兼容有關。

因為一個空的Optional代表一個不存在,這意味着該方法實際上有效但沒有返回任何結果。

但是,將hello解析為整數將不起作用並且必須拋出異常,因為它是錯誤而不是空結果。 請記住, NumberFormatException擴展了IllegalArgumentException

更一般地說, Optional用於處理可能不存在的值(而不是為此使用null ),而不是用於錯誤處理。 此外, Optional沒有提供任何方法來了解錯誤是什么以及為什么會出現錯誤。

我不想推測為什么這樣的方法不存在,但如果你既不喜歡,執行預測試也不捕獲異常,你需要重新實現,例如

public static OptionalInt parseInt(String s) {
    if(s.isEmpty()) return OptionalInt.empty();
    final int len = s.length(), limit;
    final boolean negative;
    int i = 0;
    switch(s.charAt(0)) {
        case '-':
            i=1;
            if(len==1) return OptionalInt.empty();
            negative = true;
            limit = Integer.MIN_VALUE;
            break;
        case '+':
            i=1;
            if(len==1) return OptionalInt.empty();
            // fall-through
        default:
            negative = false;
            limit = -Integer.MAX_VALUE;
    }
    final int limitBeforeMul = limit / 10;
    int result = 0;
    for(; i < len; i++) {
        int digit = Character.digit(s.charAt(i), 10);
        if(digit < 0 || result < limitBeforeMul || (result *= 10) < limit + digit)
            return OptionalInt.empty();
        result -= digit;
    }
    return OptionalInt.of(negative? result: -result);
}

這基本上與Integer.parseInt相同,但為無效字符串返回一個空的OptionalInt而不是拋出異常......

您可能已經注意到,最難的部分是處理接近於Integer.MIN_VALUE數字。 Integer.MAX_VALUE正確。

沒有 try-catch 並且仍然返回一個 Optional - 你可以做

Optional<Integer> result = Optional.ofNullable(input)
    .filter(str -> str.matches("-?\\d+"))
    .map(Integer::parseInt);

編輯:更新正則表達式以支持負數

警告:如評論中所指出的,如果解析的字符串超出Integer.MIN_VALUEInteger.MAX_VALUE的范圍,仍將拋出 RuntimeException

Google 的 Guava 庫提供了一個輔助方法來執行此操作:Ints.tryParse(String)。當字符串不可解析時,它會運行null 您可以查看文檔

使用Mutiny可以這樣寫。

如果你只是想對結果做一些事情,你可以用一個表達式來做

Uni.createFrom()
  .item(() -> Integer.parseInt(toParse))
  .onFailure().recoverWithItem(defaultValue)
  .subscribe().with(i -> System.out.println(i));

或者創建一個像預期的方法

    public static Integer parseIntOrDefault(String toParse, int defaultValue) {
        Integer[] toReturn = new Integer[]{null};
        Uni.createFrom()
           .item(() -> Integer.parseInt(toParse))
           .onFailure().recoverWithItem(defaultValue)
           .subscribe().with(i -> toReturn[0] = i);
        return toReturn[0];
}

此解決方案添加了一個庫,但該庫並非專門用於處理此問題。 它使用反應式編程、期貨、回調和流暢的 API,並被證明足夠靈活來解決這個問題。

暫無
暫無

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

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