20

我遇到了这种情况,我需要将 a 解析String为 anint而我不知道如何处理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()会引发异常。所以我唯一的做法似乎就是调用它并捕获异常。

javadoc forparseInt并没有多大帮助。

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

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

8 回答 8

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;
    }
}
于 2010-12-10T15:19:45.517 回答
10

Commons lang中有NumberUtils.toInt(String, int),它可以完全满足您的需求。

NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42
于 2010-12-10T15:07:32.760 回答
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

也就是说,不一定需要在每个异常捕获块中包含诊断日志记录。有时,最好的做法是采取默认课程。有时是与用户交互。这取决于。

于 2010-12-10T15:25:21.300 回答
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 中的标准习语,它没有提供另一个(至少我知道)。

如果我根本没有捕捉到异常,变量不会被分配吗?然后我将简单地将它初始化为我想要的值,当它不是数字并且不捕获异常时。

您必须捕获异常(即使它什么也不做),否则它会逃离块并通过堆栈抛出。

有没有办法以某种方式明确地标记我不关心的异常?我认为这将类似于 AWTEvent.consume()。如果是这样,那么我会这样做,以便 Google CodePro 不会将其视为“未记录”。

我一个都不知道。我会使用上述方便的方法(我在我的所有项目中都可以使用的一小部分通用实用程序中有类似的东西)。

如果它确实是您正在处理的正常情况,我不会记录它。我不熟悉 Google CodePro,但我希望有一种方法可以抑制警告,例如某种 @SuppressWarnings("xxx") 注释/关键字。


编辑:我想在下面的评论中指出这些评论

这种方法仍然不能处理异常。捕获异常并且不做任何事情是不好的形式。这就是为什么我正在寻找更好的解决方案

.

...通过返回指示的 valueIfInvalid来处理异常(情况) 。您所指的“不良形式”是指盲目且不假思索地编写空捕获块并且永远不会回头真正考虑和解决此案的不良做法。如果考虑到异常情况并针对该情况做了正确的事情(即使正确的事情是什么都不做),那么您已经“处理”了异常

于 2010-12-10T15:08:25.320 回答
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代码中的方法,然后单击打开声明。

于 2012-12-12T23:39:26.870 回答
0

您应该在执行过程中捕获异常。这很烦人,但最好的方法。

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

当字符串不是 int 时,将引发异常,因此您的 int 变量不会被设置,除非您在执行过程中捕获异常。

于 2010-12-10T15:02:50.660 回答
0

您的第一个代码块是正确的。i当发生异常并且您必须捕获该异常时,不会隐式转换为 0。里面设置i为0catch是正确的;尽管您可以简单地替换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;
}
于 2010-12-10T15:05:06.170 回答
0

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

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

于 2010-12-10T15:09:28.173 回答