这可能是一个奇怪的问题,但我仍然认为我应该要求深入了解这个问题,并阻止我在编码时做错误的事情。
假设我有一个函数func1(),在它里面我调用函数func2()。Func2()抛出异常e1。我想在func1()中捕获这个异常。
那么,我是否在函数本身的开头开始一个try块,并在func1()的末尾用catch块结束它,而不是仅仅围绕在调用函数func2()的代码部分,这有关系吗?
我知道从编码器的角度来看,如果一个异常被抛出,他将能够确切地知道异常来自哪里。如果我们忽略这一点,那么仅仅将整个方法放在try-catch中是否还有其他不良影响?
编辑代码片段
所以我将JSON字符串转换为JSON节点。这个操作抛出一个异常。但是我没有用try-catch块包围这一条语句,而是把整个函数放在try块中。在我看来更干净。:)
public void storePublicData(String publicData, String twitterId) {
try {
Date date=new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String day = formatter.format(date);
BasicDBObject query = new BasicDBObject("date", day);
query.append("brand_id", twitterId);
JsonNode publicDataJsonNode;
publicDataJsonNode = JSONOperations.castFromStringToJSONNode(publicData);
DBObject document = BasicDBObjectBuilder.start()
.add("brand_id", twitterId)
.add("date", day)
.add("followers", publicDataJsonNode.get("followersCount").asText())
.add("tweets", publicDataJsonNode.get("tweetsCount").asText())
.get();
twitterCollection.update(query,new BasicDBObject("$set", document), true, false);
} catch (JSONParamsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
最大的缺点是您可能还会捕捉到您没有打算捕捉的异常。
例如,假设您有一个可能抛出NullPointerException
的方法,并且您可以处理这种情况。(这样的方法可能写得很糟糕,但假设它是一个库方法,您无法更改它。)所以,你抓住了NPE:
void func1() {
try {
func2();
if (someString.equals("some value") {
someOtherFunction();
}
} catch (NullPointerException e) {
// handle func2()'s NPE somehow
}
}
有两个位置可以在try
的主体中抛出NPE:从func2
,或者如果someString
是null
则从someString.equals
。这段代码以相同的方式处理两者,这可能是一个bug。
一般来说,在编程的几乎所有方面(变量作用域、try-catch块、类成员等),作用域越小,越容易推理,编写错误的可能性也越小。
显然可以在整个方法体周围使用try/catch块,但是将其限制在预期会出现错误的区域可以增加代码的可读性。我也相当肯定,他们是非常缓慢,效率低下,没有"尝试"的东西,没有可能的IOException例如int i = 2 + 2;
我知道从编码员的角度来看,如果抛出异常,他将能够确切地知道异常来自何处
你说对了:当你写一个方法时,你在你和用户之间创建了一个契约。如果你声明该方法抛出了一个异常——捕捉并处理该异常将是用户的责任。如果有意义,您应该这样做(例如,如果打开到DB的连接失败,则抛出异常)。也就是说,在其他情况下,您可能希望执行回退并仅向用户报告操作是否成功,在这种情况下,您可以用try/catch包围method2中的所有代码并返回一个布尔值,从而为用户节省处理异常的额外代码。
如果在调用funct2之后在funct1中有任何内容,那么如果将整个方法放入try-catch中,则不会执行。
我引用Clean Code Book:
错误处理是一个任务,函数也应该完成一个任务。因此,处理错误的函数不应该做任何其他事情。这意味着(如上面的例子所示),如果关键字try存在于函数中,它应该是函数中的第一个单词catch/finally语句块之后应该什么都没有
所以你应该创建一个方法来管理异常,就像这样:public class Test {
public void doSomthing(){
// here i don't need to manage the exception because i have built parseDate(String date)
Date date = parseDate("10-17-2016");
}
private Date parseDate(String date){
Date result = null;
try {
result = new SimpleDateFormat().parse(date);//Throws Parse Exception
} catch (ParseException e) {
// Here you can:
//1) Throws other exception (Checked or Unchecked)
//2) Log the exception
// I think you should not re-throws the exception because
//is responsibility of this methods manage the exception
e.printStackTrace();
}
return result;
}
}