在预期时处理NumberFormatException的正确方法是什么?

时间:2010-12-10 15:01:37

标签: java exception try-catch numberformatexception

我遇到了这种情况,我需要将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()是否会抛出异常。因此,我唯一的行动方式似乎就是调用它并捕获异常。

parseInt的{​​{3}}无济于事。

以下是我想知道的具体问题:

  • 我可以调用一种方法,告诉我Integer.parseInt()在调用之前是否会抛出NumberFormatException吗?然后我就没有问题记录这个,因为它永远不会发生。
  • 如果我只是没有抓住异常,那么是否可以分配?然后我会简单地将它初始化为我想要的值,当它不是数字时,不会捕获异常。
  • 有没有办法明确标记异常我不关心它?我认为这与AWTEvent.consume()类似。如果是这样,那么我会这样做,以便Google CodePro不会将其视为“未记录”。

8 个答案:

答案 0 :(得分:13)

  • 是否有一个我可以调用的方法,它会告诉我Integer.parseInt()在调用之前是否会抛出NumberFormatException?然后我就没有问题记录这个,因为它永远不会发生。

可悲的是,没有。至少不在核心Java API中。然而,编写一个很容易 - 只需修改下面的代码即可。

  • 如果我只是没有抓住异常,那么是否可以分配?然后我会简单地将它初始化为我想要的值,当它不是数字时,不会捕获异常。

如果你没有捕获异常,那么堆栈将展开直到它遇到一个将处理它的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;
    }
}

答案 1 :(得分:9)

NumberUtils.toInt(String, int)commons lang可以完全按照您的意愿行事。

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42

答案 2 :(得分:3)

* 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块中包含诊断日志记录。有时,最好的方法是采取默认课程。有时它是与用户交互的。这取决于。

答案 3 :(得分:1)

为现在和将来的使用创建自己的便利方法:

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来处理异常(情况) “糟糕的形式” 你指的是盲目且不假思索地写空空挡块的糟糕的做法并且永远不会回到真正考虑和解决案子。如果考虑了异常情况,并为情况做了正确的事情即使正确的事情是什么都不做),那么你已经“处理”了例外

答案 4 :(得分:0)

你应该像你一样抓住异常。这很烦人,但最好的方法。

当字符串不是有效的int时,没有Java API方法返回0。

当字符串不是int时,将抛出异常,因此除非您像现在一样捕获异常,否则不会设置int变量。

答案 5 :(得分:0)

您的第一个代码块是正确的。发生异常时,i不会隐式转换为0,您必须捕获该异常。在i内将catch设置为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;
}

答案 6 :(得分:0)

如果不清楚你应该如何从吸气器处理它,你就不应该抓住它并让呼叫者处理它。如果你知道应该如何处理它,你应该这样做。在这种情况下,记录它可能不是必需的或非常有用。

如果您不知道如何处理异常,并且将其留给阅读日志的人员,则记录异常会更有用。

答案 7 :(得分:0)

正如其他人所提到的,没有内置的核心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,然后单击“打开声明”。