我必须解析一个可以采用十六进制值或其他非十六进制值的字符串
0xff
,0x31
或A
,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制作一个简单的装配器。
答案 0 :(得分:7)
异常处理是Java编程语言不可或缺的一部分(也是设计目标之一)......你不应该因为你认为它们“丑陋”而将它们抛弃。
也就是说,如果您想要一种简单易读的方式来处理NumberFormatException
,您可以考虑使用NumberUtils
类。
toInt(String str, int defaultValue)
方法将String
转换为int
,如果转换失败则返回默认值。如果字符串为null
,则返回默认值。
NumberUtils.toInt(null, 1) = 1
NumberUtils.toInt("", 1) = 1
NumberUtils.toInt("1", 0) = 1
该方法封装了异常捕获和处理,如下面的source code所示。因此,客户端只需要进行一次方法调用。
public static int toInt(String str, int defaultValue) {
if(str == null) {
return defaultValue;
}
try {
return Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return defaultValue;
}
}
答案 1 :(得分:2)
你的问题是我今天看到的第二个问题。
不,抓住这个例外非常合适。
更好的形式来捕获更明确的异常(如“NumberFormatException”)而不是通用的“异常”。
... IMHO
PS: 在哪里你提出异常:在这个级别或更高级别,是一个不同的问题。
经验法则是“你知道发生了什么的最低级别,以及如何最好地恢复。”
或者,换句话说(引用下面的链接):
“一个方法只有在能够以合理的方式处理它时才能捕获异常。”
以下是一些讨论:
答案 2 :(得分:1)
不,这不是“糟糕的做法”。这取决于具体情况。
例如,作为Android,如果用户将字符串“123a”输入到仅应接受整数的文本框中,并随后进行解析,则会引发异常,从而导致应用程序崩溃。在这种情况下,捕获异常并提示用户重新输入文本将非常有意义。
答案 3 :(得分:1)
在您的情况下,我希望使用isHexDigit
方法之类的方法来使用NumberFormatException
,除非您对数据的格式有一些假设 - 从您的描述看似乎没有关于何时会遇到十六进制数与非十六进制数的假设。
这是因为异常应该用于处理异常条件,并且如果数据的期望是:十六进制数字或非十六进制数字,用空格分隔然后遇到一个非十六进制数字的令牌没有什么特别之处。
此外,使用Exception 使代码不易读取:没有关于数据的注释,它隐藏了散布的非十六进制数字是可接受的和预期输入的事实。
说明了这个偏好后,我可能会使用异常处理来处理这种情况,我当然看到很多代码都这样做了。在decode / parseInt / NumberFormatException的组合中为您提供了许多好的功能。如果没有明确解释我正在做什么的明确评论,我就不会使用它。
答案 4 :(得分:0)
这取决于上下文,在很多情况下它很糟糕但是如果它将是一个非常可能有错误输入的地方而你有一个默认设置它然后你想要抓住它。
答案 5 :(得分: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可以按任何顺序......
答案 6 :(得分:0)
这是你能做的最好的事情。一个方法要么返回某种成功/错误指示器,要么抛出异常,这只是一个最方便的问题。在这里,Sun为我们做出了决定,因此无需进行辩论。
对此我的错误是,该异常将包括完整的堆栈跟踪!在您的特定情况下,如果您正在阅读数百万这些字符串,那么 会注意到(完全不必要的)性能不佳。如果对您很重要,您可能需要考虑编写自己的方法(可以使用Sun代码作为指导。)然后您可以自己决定是否要使用异常。如果这样做,请保留异常的静态副本,并始终将其抛出以节省分配时间。并覆盖fillInStackTrace
,因此它不会执行任何操作,并且您的异常中没有无意义的堆栈跟踪。