Java的Try Catch块大小

4

这可能是一个奇怪的问题,但我还是想问一下,以便了解更多信息,并防止我在编码时做错事情。

假设我有一个函数func1(),在其中调用了一个函数func2()。func2()抛出异常e1。我想在func1()中捕获这个异常。

那么,在函数本身的开头开始try块并在func1()的结尾结束它并使用catch块,是否比仅仅将代码的一部分包含在调用函数func2()的try块中更重要?

我知道从编码人员的角度来看,如果抛出异常,他将能够准确地知道异常来自哪里。如果我们忽略这一点,只是将整个方法放置在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();
    }

}

如果您添加一些代码片段,那么您的问题将更有价值。 :) 无论如何,这个问题最好放在[codereview.SE]或[Programmers.SE]上。 - try-catch-finally
哈,这个问题的用户名非常合适 :) 同意,放在程序员板块可能更好一些。 - nerdherd
添加了一段代码片段。 :) 希望现在这是一个更有价值的问题.. :D - Sambhav Sharma
5个回答

3

最大的缺点是你可能会捕获到你没有打算捕获的异常。

例如,假设你有一个可能抛出NullPointerException的方法,并且你可以处理这种情况。(这样的方法可能写得很糟糕,但假设它是一个库方法,你不能改变它。)因此,你捕获了NPE:

void func1() {
    try {
        func2();
        if (someString.equals("some value") {
            someOtherFunction();
        }
    } catch (NullPointerException e) {
        // handle func2()'s NPE somehow
    }

}

这段代码中,NPE可能在try块体内的两个地方抛出:从func2中或从someString.equals(如果someString为null)中。这段代码对两种情况都采取了相同的处理方式,这很可能是一个bug。

通常来说,在编程的几乎所有方面(变量作用域、try-catch块、类成员等),作用域越小,理解起来就越容易,出现bug的可能性也越小。


2

你可以显然地在方法的整个主体周围使用try/catch块,但将其限制在您期望出现错误的区域可以增加代码的可读性。我也相当确定它们非常慢且低效,并且在没有可能出现IOException的情况下'try'某事毫无意义,例如 int i = 2 + 2;


3
仅使用 try-catch 块并不会很慢,而是抛出(和记录)异常的过程慢。如果没有抛出异常,使用 try-catch 的性能问题是一个有趣的问题:https://dev59.com/h2Qn5IYBdhLWcg3w7a2K - nerdherd
谢谢你,我很感激这个链接!非常有趣的是编译器不会优化 try 语句块内的代码。 - Tom McGee

2

我知道从程序员的角度来看,如果抛出异常,他将能够准确地知道异常来自哪里

你说得对:当你编写方法时,你与用户之间创建了一份合同。如果你声明该方法会抛出异常 - 这将是用户捕获和处理异常的责任。如果有意义 - 你应该这样做(例如,如果无法打开到数据库的连接,则抛出异常)。话虽如此,在其他情况下,你可能希望执行回退并仅向用户报告操作是否成功,在这种情况下,你可以用try/catch包围method2中的所有代码并返回布尔值以节省用户处理异常的额外编码。


0

我在引用《Clean Code》这本书:

处理错误只是一项工作,函数应该只做一件事。因此,处理错误的函数不应该有其他功能。这意味着(就像上面的例子)如果一个函数存在 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;
  }

}

0

嗯,如果在调用 funct2 后的 funct1 中有任何内容,则如果将整个方法放在 try-catch 中,该内容将不会被执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接