Java Try Catch Block Size



这可能是一个奇怪的问题,但我仍然认为我应该要求深入了解这个问题,并阻止我在编码时做错误的事情。

假设我有一个函数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,或者如果someStringnull则从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;
  }
}

最新更新