10

我必须解析一个可以假定十六进制值或其他非十六进制值的字符串

0xff,0x31A, PC, label, 等等。

我用这段代码来划分两种情况:

String input = readInput();

try {
    int hex = Integer.decode(input);            
    // use hex ...

} catch (NumberFormatException e) {
   // input is not a hex, continue parsing
}

这段代码可以被认为“丑陋”或难以阅读吗?还有其他(也许更优雅)的解决方案吗?

编辑:我想澄清一下(在我的情况下)不存在错误的输入:我只需要区分它是否是十六进制数字。为了完整起见,我正在为DCPU-16制作一个简单的汇编程序。

4

7 回答 7

7

异常处理是 Java 编程语言的一个组成部分(也是设计目标之一)......你不应该仅仅因为你认为它们“丑陋”而抛弃它们。

也就是说,如果您想要一种简单易读的方式来处理NumberFormatExceptions,您可以考虑改用NumberUtils该类。

toInt(String str, int defaultValue)方法将 a 转换为 a Stringint如果转换失败,则返回默认值。如果字符串为null,则返回默认值。

 NumberUtils.toInt(null, 1) = 1
 NumberUtils.toInt("", 1)   = 1
 NumberUtils.toInt("1", 0)  = 1

该方法封装了异常捕获和处理,如下面的源代码所示。因此,客户端只需要进行一次方法调用。

public static int toInt(String str, int defaultValue) {         
    if(str == null) {
        return defaultValue;
    }
    try {
        return Integer.parseInt(str);
    } catch (NumberFormatException nfe) {
        return defaultValue;
    }
}
于 2012-06-22T20:02:14.460 回答
2

你的问题是我今天看到的第二个问题。

不,捕捉这个异常是非常合适的。

与一般的“异常”相比,捕获更明确的异常(如“NumberFormatException”)绝对是更好的形式。

恕我直言...

PS: 你把例外放在哪里:在这个级别或更高级别,是一个不同的问题。

经验法则是“您知道发生了什么以及如何最好地恢复的最低级别”。

或者,换一种说法(引用下面的链接):

“一个方法应该只在它能够以某种合理的方式处理异常时才捕获它。”

这里有一些讨论:

于 2012-06-22T19:15:37.933 回答
1

不,这不是“坏习惯”。这取决于情况。

例如,作为一个Android,如果用户在一个应该只接受整数的文本框中输入一个字符串“123a”,并且随后被解析,则会抛出异常导致应用程序崩溃。在这种情况下,捕获异常并提示用户重新输入文本是非常有意义的。

于 2012-06-22T19:18:01.830 回答
1

在您的情况下,我更喜欢使用isHexDigit方法之类的东西NumberFormatException,除非您可以对数据格式做出一些假设 - 从您的描述来看,似乎没有关于何时遇到十六进制数字与. 非十六进制数字。

这是因为应该使用异常来处理异常情况,并且如果您对数据的期望是:十六进制数字或非十六进制数字,以空格分隔,那么遇到除十六进制数字之外的标记没有什么异常。

此外,使用异常确实会降低代码的可读性:没有对数据的注释,它隐藏了散布的非十六进制数字是可接受的和预期的输入的事实。

说明了这种偏好后,我可能会使用异常处理来处理这种情况,而且我当然看到很多这样做的代码。decode/parseInt/NumberFormatException 的组合为您提供了许多好的功能。如果没有明确解释我在做什么的明确评论,我不会使用它。

于 2012-06-22T19:44:46.653 回答
0

这取决于上下文,在许多情况下它很糟糕,但如果它是一个很可能有错误输入的地方并且你有一个默认设置,那么你会想要抓住它。

于 2012-06-22T19:14:49.570 回答
0

它的Not about how good you code looks,但是how good your code works………… Ya offcourse it should be readable, 正如那句名言……

任何傻瓜都可以编写计算机可以理解的代码,但只有伟大的程序员才能编写人类可以理解的代码。

在某些情况下它完全没问题,你需要有这样的例外。

When you want to catch multiple exceptions which belong to the same inheritance tree, then create a try block, and multiple catch blocks from more specific to more abstract.

例如:

`Animal <--- Carnivores <--- Dog`

现在假设有一个DogException, CarnivoresException, AnimalException

那么一定是这样的,

try{

           // your code 

     }
      catch(DogException d){}
      catch(CarnivoresException c){}
      catch( AnimalException a){}

上面的捕获已经从更具体到更抽象级联,以便异常被捕获到它的原因。

如果没有继承,那么 catch 可以按任何顺序...

于 2012-06-22T19:25:26.000 回答
0

这是你能做的最好的。方法要么返回某种成功/错误指示符,要么抛出异常,这只是哪个最方便的问题。在这里,Sun 为我们做出了决定,因此无需辩论。

让我感到困扰的是,异常将包含完整的堆栈跟踪!在您的特定情况下,如果您正在阅读数百万个这些字符串,您注意到(完全不必要的)性能不佳。如果这对您很重要,您可能需要考虑编写自己的方法(您可以使用 Sun 代码作为指导。)然后您可以自己决定是否要使用异常。如果这样做,请保留异常的静态副本并始终将其抛出以节省分配时间。并覆盖fillInStackTrace所以它什么都不做,并且您的异常中没有毫无意义的堆栈跟踪。

于 2012-06-22T20:09:25.597 回答