在try块中返回vs在块之后返回

时间:2015-08-04 02:18:34

标签: java return try-catch

我在一个小的静态方法中有一个try语句,有关于我应该从哪里返回的最佳实践吗?

try {
    mightThrow();
    return true;
} catch (Exception e) {
    return false;
}

或之后,

try {
    mightThrow();
} catch (Exception e) {
    return false;
}
return true;

从功能上讲,这些应该预先形成相同的,实际上是否存在字节码差异?性能方面,它们是完全相同吗?

或者一个人比另一个更受欢迎?哪个以及为什么?

3 个答案:

答案 0 :(得分:8)

我没有听说过这个问题的实际最佳做法,但是你经常看到当方法使用过早返回时,返回true的情况就在底部,例如。

public bool canReadFile(path) {
  if (!fileExists(path))  
    return false;

  if (!fileIsReadable(file))
    return false;

  ...
  return true;
}

因此,我建议你按照这种方法进行try / catch块。它还可以更快地查看“预期”返回值是什么。

关于字节码,那么是的,确实存在差异。我做了一个快速的示例程序

class TryBlock {
    public static void main(String[] args) {
        a();
        b();
    }

    public static boolean a() {
        try {
            System.out.println("A");
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean b() {
        try {
            System.out.println("B");
        } catch (Exception e) {
            return false;
        }
        return true;
    }

}

然后编译并检查字节码

$ javac TryBlock.java; javap -c TryBlock
Compiled from "TryBlock.java"
class TryBlock {
  TryBlock();
    Code:
       0: aload_0
       // Method java/lang/Object."<init>":()V
       1: invokespecial #1                  
       4: return

  public static void main(java.lang.String[]);
    Code:
       // Method a:()Z
       0: invokestatic  #2                  
       3: pop
       // Method b:()Z
       4: invokestatic  #3                  
       7: pop
       8: return

  public static boolean a();
    Code:
       // Field java/lang/System.out:Ljava/io/PrintStream;
       0: getstatic     #4                  
       // String A
       3: ldc           #5                  
       // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       5: invokevirtual #6                  
       8: iconst_1
       9: ireturn
      10: astore_0
      11: iconst_0
      12: ireturn
    Exception table:
       from    to  target type
           0     9    10   Class java/lang/Exception

  public static boolean b();
    Code:
       // Field java/lang/System.out:Ljava/io/PrintStream;
       0: getstatic     #4                  
       // String B
       3: ldc           #8                  
       // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       5: invokevirtual #6                  
       8: goto          14
      11: astore_0
      12: iconst_0
      13: ireturn
      14: iconst_1
      15: ireturn
    Exception table:
       from    to  target type
           0     8    11   Class java/lang/Exception
}

那么性能差异是什么?虽然我没有测试,但我的赌注是没有任何明显的东西。最重要的是,这几乎不是您申请的瓶颈。

答案 1 :(得分:2)

对我而言,这更像是语义和可读性问题。

如果你的return true位于try/catch块之外的段的末尾,则意味着该函数应该返回true值,除非在它们之间发生中断正常流的任何不良情况。

相反,如果return true位于try块的末尾,则表示如果try块中的所有尝试都成功,则该函数应该只返回true。

这种字节码的差异或多或少可以忽略不计;我同意@kba这更像是一个风格问题。在深度嵌入的return块内的不同位置的许多if语句通常会令人困惑;因此,使代码不那么复杂是一种很好的做法。即。

  1. 尽可能使用平嵌块而不是深嵌入
  2. 将较少的状态转移到另一个代码段和/或内部iffortry
  3. 使用较少的状态和流量控制变量
  4. 使用较少的语句,如returngo,因为它们或多或少是逻辑流程的强制更改。
  5. 希望有所帮助。

答案 2 :(得分:0)

对于任何类型的异常,返回始终设置为false。这可能不是您期望的情况。可能是某些意外的异常会导致返回false值。所以不是一个很好的标准回归方式

相关问题