在java中使用一个大的try-catch per方法是一个众所周知的好习惯吗?

Adr*_*rez 58 java exception-handling try-catch

我最近接受过采访,面试官希望我做一个技术测试,看看我的知识.在我完成它之后,他给了我关于我是如何做到这一点的反馈,这是我没想到的,我很感激,因为如果他们不想雇用你,很少有采访者这样做.

他告诉我他告诉我他的代码不好的一件事是我在我编写的每个方法中使用了多个try-catch块.这引起了我的注意,因为我觉得它很有趣.

我相信目前我应该创建try-catch块,其中有一个语义可区分的代码块,它有一个或多个方法可以抛出需要捕获的异常.我遵循的唯一例外是,如果两个方法抛出相同的异常类型,我最好将它们放在不同的try-catch块中,以清楚地区分调试抛出异常的位置和原因.

这与采访者希望我做的完全不同.那么每种方法只使用一个try-catch块是一种已知的良好实践吗?如果这是一个众所周知的良好做法,这样做有什么好处?

编辑:我非常感谢您对此的看法,这非常好.虽然请注意我在问这是否是一个已知的良好做法.这是,如果大多数程序员都同意这一点,或者这是一本书中的好习惯

Bar*_*cki 40

对我来说,两个try-catch块使大多数方法太长.如果方法做了很多事情,它会混淆意图.

有两个try-catch块,准确地说它至少做了四件事

  • 主流两种情况(两个试块)
  • 错误处理的两种情况(catch块)

我宁愿在每个try-catch块中制作简短明了的方法

private getHostNameFromConfigFile(String configFile, String defaultHostName) {
    try {
        BufferedReader reader = new BufferedReader(new FileReader(configFile));
        return reader.readLine();
    } catch (IOException e) {
        return defaultHostName;
    }
}
public Collection<String> readServerHostnames(File mainServerConfigFile, File  backupServerConfigFile) {
    String mainServerHostname=getHostNameFromConfigFile(mainServerConfigFile,"default- server.example.org");
    String backupServerHostName=getHostNameFromConfigFile(backupServerConfigFile,"default- server.example.ru")
    return Arrays.asList(mainServerHostname,backupServerHostName );
}
Run Code Online (Sandbox Code Playgroud)

"清洁代码"中的Robert C. Martin将其提升到了新的水平,表明:

如果关键字'try'存在于函数中,它应该是函数中的第一个单词,并且在catch/finally块之后应该没有任何内容.

我肯定会使用两个单独的try/catch块将方法重构为更小的方法.

  • 因为你找到了我想找到的东西,我更喜欢你的答案; 即一个好的和着名的引用,建议或鼓励只为每个方法/函数编写一个try-catch,并说明这样做的原因.似乎最后我会从面试官那里学到一些东西. (3认同)

Old*_*eon 30

我要说如果你发现自己包装了两个独立的代码块,try/catch你应该考虑将这些块重构为单独的方法.如果这是你在面试中使用的模式,可能是你误解了面试官.

try/catch如果算法需要,使用两个块是完全正常的.我经常try/catch在catch块中使用new 来确保安全清理,因此无法进行全面的声明.

  • +1同意.方法应该只用于一个目的. (6认同)
  • 此外,如果你在同一个try/catch中包含两个单独的代码块,那么你就无法在catch块中实现一个适当的恢复算法而不必区分这两种情况,使用"if",哪种类型的目的会失败捕获并使其比必要的更复杂. (3认同)
  • 这是最好的答案,因为它承认实际问题. (2认同)

dha*_*ram 14

要回答你的问题,当我们谈论实际在代码中应用大量优化的现代JVM时,当你编写一些效率低下的代码时,JVM会自动引入优化.

请参考答案(Java:输入/使用"try-catch"块的开销?).

所以好的做法并不重要.

就我个人而言,我认为,一个不得以任何封装try-catch,static,synchronized等块未必然.

让我们让我们的代码对那些将要解决这个问题的人更具可读性.如果捕获到异常,最好明确说明哪一段代码正在抛出它.

不要猜测读者,这就是为什么JVM很聪明,可以根据需要编写,让人们更好,JVM负责优化部分.

编辑:我已经阅读了大量的书籍,我没有找到任何一个地方,说一个大尝试捕获比多个小的更好.

此外,开发者社区中的许多人都认为相反.

  • 谢谢@dharam,这就是我一直在寻找的答案。我们每个人都有理由考虑以一种或另一种方式来操作这个 try-catch 块,以获得更好的干净代码或性能。尽管如果人们同意你的观点;也就是说,不知道有什么好的做法,那么我发现用个人偏好来判断工作候选人并不是一个好方法。我希望根据普遍接受的内容来进行评判,然后被告知按照团队对代码风格的偏好进行编码。我本以为能从面试官那里学到一些东西,看来我不会。:/ (2认同)

Tom*_*son 9

我尽量避免在catch块中重复.如果方法中的所有异常在catch块中都接受相同的处理,那么继续将它们全部捕获.如果你需要对它们做不同的事情,那么分别抓住它们.

例如,在这里我们可以一起捕获所有异常,因为任何类型的异常都意味着整个方法失败:

public PasswordAuthentication readAuthenticationDetails(File authenticationFile) {
    try {
        BufferedReader reader = new BufferedReader(new FileReader(authenticationFile));
        String username = reader.readLine();
        String password = reader.readLine();
        return new PasswordAuthentication(username, password.toCharArray());
    } catch (IOException e) {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们对每组调用都有不同的回退行为,因此我们分别抓住:

public Collection<String> readServerHostnames(File mainServerConfigFile, File backupServerConfigFile) {
    String mainServerHostname;
    try {
        BufferedReader reader = new BufferedReader(new FileReader(mainServerConfigFile));
        mainServerHostname = reader.readLine();
    } catch (IOException e) {
        mainServerHostname = "default-server.example.org";
    }

    String backupServerHostname;
    try {
        BufferedReader reader = new BufferedReader(new FileReader(backupServerConfigFile));
        backupServerHostname = reader.readLine();
    } catch (IOException e) {
        backupServerHostname = "default-server.example.ru";
    }

    return Arrays.asList(mainServerHostname, backupServerHostname);
}
Run Code Online (Sandbox Code Playgroud)

(这段代码纯粹是为了说明关于捕获异常的这一点;我请求你忽略这样一个事实,即在其他方面它是完全可怕的)


ssa*_*tos 6

至于我,只有一个try-catch块包含一个方法中的所有"危险"代码更清楚.关于两条线路抛出相同异常时应该责怪谁,你将始终拥有堆栈跟踪.

此外,try-catch在一个方法中有一个以上的方法通常意味着有一个以上的return行(也可能很难在一个视线上执行代码执行),因为如果第一个出现问题的可能性很小try-catch,那么就没有意义继续运行剩下的代码.

在这里,您可以找到一些"标准"最佳实践,以防您发现它们有用.-

http://howtodoinjava.com/2013/04/04/java-exception-handling-best-practices/


Eel*_*Lee 5

这是另一件经常启动Java-flamewar ...... ;-)

基本上,对于性能问题只会抛出异常.因此,使用少量try-catch块不应该影响性能.在某些意见中,编写代码可能会混淆代码并且甚至不会回想起"干净的代码",在其他人看来,最好try只使用可以实际抛出任何异常的行.

这取决于你(或团队惯例).


Chr*_*ris 5

考虑代码的上下文也很重要.如果您正在编写具有大量IO的代码,那么您可能需要知道代码的哪些部分失败.我没有看到任何地方尝试......捕捉意味着让你有机会从问题中恢复过来.

因此,如果从一个文件读取时出现IO异常,则可能需要重试读取.与写作相同.但是,如果你有一个大的尝试...抓住你不知道哪个重试.