在预期时处理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希望我以某种方式记录exception,我同意这是最佳做法。

 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()返回的默认值?

一般风格说如果我捕获exception,我应该在某处记录它。 我不想记录它。 这种exception有时被抛出是正常的操作,这对我来说也不合适。 但是,我找不到一个函数,它会告诉我Integer.parseInt()是否会抛出exception。 所以我唯一的行动方式似乎就是调用它并捕获exception。

parseInt的javadoc没有多大帮助。

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

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

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

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

  • 如果我只是没有捕获exception,那么valiable会不会被分配? 然后我会简单地将它初始化为我想要的值,当它不是数字而不是捕获exception时。

如果你没有捕获exception,那么堆栈将展开,直到它遇到将处理它的catch块,或者它将完全展开并停止线程。 事实上,该变量不会被分配,但这并不是您想要的。

  • 有没有办法明确标记exception,我不关心它? 我认为这将类似于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

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

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

 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? 然后我就没有问题记录这个,因为它永远不会发生。

不是我知道的。 请记住,如果有,您可能最终解析该值两次(一次validation,一次解析)。 我理解你想要避免exception,但在这种情况下,这是捕获exception是Java中的标准习语,它不提供另一个(至少我知道)。

如果我只是没有捕获exception,那么valiable会不会被分配? 然后我会简单地将它初始化为我想要的值,当它不是数字而不是捕获exception时。

你必须捕获exception(即使它什么都不做),否则它将逃脱阻塞并向上抛出堆栈。

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

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

如果它真的是你正在处理的正常状态,我不会记录它。 我不是谷歌CodePro的家庭,但我希望有一种方法来抑制警告,例如某种@SuppressWarnings(“xxx”)注释/关键字。


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

这种方法仍然没有处理exception。 捕获exception并对其无所作为是一种糟糕的forms。 这就是为什么我在寻找更好的解决方案

…通过返回指示的valueIfInvalid 来处理exception(情况)。 “糟糕的forms”你指的是盲目地,不假思索地写空陷阱不良做法,从不回过头来真正考虑并解决这个问题。 如果考虑exception情况并且对情况做了正确的事情即使正确的事情是什么都不做 ),那么你已经“处理”了exception

您应该像正在做的那样捕获exception。 这很烦人,但最好的办法。

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

当字符串不是int时,将抛出exception,因此除非您按原样捕获exception,否则不会设置int变量。

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

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

你的第一个代码块是正确的。 当发生exception并且您必须捕获该exception时, i不会被隐式转换为0。 将catch设置为0是正确的; 虽然你可以简单地取代i = 0; return 0; 。 在这种情况下,您无法避免exception处理。

为了澄清,你可以使用这个:

 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; } 

正如其他人所提到的,没有可以调用来validation整数的内置核心Java API方法,但是您可以使用Character类来validation输入而不使用exception处理。 例如:

 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源代码中validation它。 (对不起,我会在这里包含parseInt方法,但我不确定我是否允许根据许可条款。)如果您正在使用Eclipse并且您的项目附有JRE源代码,那么您可以- 在代码中单击Integer.parseInt方法,然后单击“打开声明”。