我有几个关于在Java中最好地使用异常的问题。
请考虑以下代码:
private String doHttpGetRequest(String url) throws IOException {
...
}
private Photo processJson(String json) throws JSON Exception{
...
}
private Photo getPhoto() throws IOException, JSON Exception {
String url = "http://...";
String response = doHttpGetRequest(url);
Photo photo = processJson(response);
photo.downloadImage();
return photo;
}
public static void main(String args[]) {
Photo p = null;
try {
p = getPhoto();
} catch( JSONException j ) {
// Re-try a few times, then display user alert
} catch( IOException e ) {
// Re-try a few times, then display user alert
}
if( p!=null)
// now display photo
}
此代码适用于连接可能不太可靠的Android应用程序,因此我想重新尝试几次getPhoto()方法以查看它是否可行,然后失败并提醒用户。 / p>
我的问题:
我在doHttpGetRequest()中打开一个InputStream,该方法抛出IOException。如果它抛出异常,我如何关闭InputStream?如果没有允许我关闭资源的方法中的finally块,我很困惑。
在main()中,我只对getPhoto()是否有效感兴趣。我是否更好地使用try / catch块在getPhoto()中包围语句并捕获JSONException,在捕获时抛出新的IOException?这将导致只需要在main()中捕获一种异常,从而导致更简单的代码并且没有重复的功能。
如果p.getPhoto()抛出异常,我想重新尝试它(可能两次)然后在失败时显示用户警报。这样做是否有共同的编程结构?
答案 0 :(得分:1)
doHttpGetRequest()
应该负责关闭输入流。最后一块将适合关闭(为什么你不想最终阻止?)。
您是否必须将任何例外传递给main方法。你可以用doHttpGetRequest(url)
包围try{}
并用另一个包围processJson
(我认为这个没有从重试中获益)。这将使main()
方法更清晰。
如果你按照我的建议继续2.你可以像这样重试:
String response = null;
for (int i = 0; i < RETRY_COUNT && response == null; i++){
try {
response = doHttpGetRequest(url);
} catch (IOException e){
// Possibly log the error here
}
}
if (response == null) return null;
编辑:修正错误
答案 1 :(得分:0)
您可以捕获异常,清理并重新抛出异常。为什么要避免使用finally
阻止?它看起来很适合那里。
分别处理这两个例外的代码可能更多。
将其置于for
循环中,continue
如果有异常,break
如果没有。
答案 2 :(得分:0)
您仍然应该使用try-finally块,以便能够关闭资源。该块使用如下:
InputStream is;
try {
is = openStream(); //This is a sample code, which
//Do something with the stream
} finally {
if (is != null) is.close();
}
这样一来,如果抛出异常,无论如何都会关闭流,异常将在别处处理。
我建议你创建自己的异常(例如,PhotoReadingException)并从getPhoto()中抛出它,但是通过initCause(Throwable cause)
方法将其原因设置为原始异常。
当然,您可以使用循环和变量来显示操作是否成功。
Photo p = null;
Exception ex = null;
for (int tries = 0; tries < MAX_TRIES; tries++) {
try {
p = getPhoto();
break;
} catch (PhotoReadingException photoException) {
ex = photoException;
}
}
if (ex != null) reportException(ex);