return 在 try 块中 vs return 在块之后
return in try block vs return after the block
我在一个小型静态方法中有一个 try 语句,关于我应该从哪里 return 是否有最佳实践?
try {
mightThrow();
return true;
} catch (Exception e) {
return false;
}
或之后,
try {
mightThrow();
} catch (Exception e) {
return false;
}
return true;
在功能上,这些 应该 执行相同,实际上是否存在字节码差异?性能方面,它们 完全 相同吗?
或者只是一个比另一个更受欢迎?哪个以及为什么?
我还没有听说过这方面的实际最佳实践,但是您经常看到当方法使用过早的 returns 时,returns true
的情况是底部,例如
public bool canReadFile(path) {
if (!fileExists(path))
return false;
if (!fileIsReadable(file))
return false;
...
return true;
}
因此,我建议您对 try/catch 个块遵循此做法。它还可以更快地查看 "expected" return 值是什么。
关于字节码,是的,确实有区别。我制作了一个快速示例程序
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
}
所以有性能差异吗?虽然我还没有测试过,但我敢打赌不会有任何明显的变化。最重要的是,这几乎不会成为您应用程序的瓶颈。
对我来说,这更多是语义和可读性问题。
如果你的 return true
在 try/catch
块之外的段的末尾,这意味着这个函数应该是 return 真值,除非在这两者之间发生了任何不好的事情中断正常流量。
相反,如果 return true
位于 try
块的末尾,则意味着只有在 try 块中的所有尝试都成功时,该函数才应该 return 为真。
这种字节码的差异或多或少可以忽略不计;我同意@kba,这更像是一个风格问题。许多 return
语句在深度嵌入 if
块内的不同位置通常会造成混淆;所以让你的代码不那么复杂是个好习惯。即
- 尽可能使用平面块而不是深度嵌入
- 将较少的状态携带到另一个代码段and/or内部
if
、for
或try
块
- 使用较少的状态和流量控制变量
- 少用像
return
或go
这样的语句,因为它们或多或少是逻辑流程的强制性改变。
希望对您有所帮助。
对于任何类型的异常,Return 始终设置为 false。这可能不是您所期望的情况。可能某些意外异常会导致返回错误值。所以在 catch
中返回不是一个好的标准方式
我在一个小型静态方法中有一个 try 语句,关于我应该从哪里 return 是否有最佳实践?
try {
mightThrow();
return true;
} catch (Exception e) {
return false;
}
或之后,
try {
mightThrow();
} catch (Exception e) {
return false;
}
return true;
在功能上,这些 应该 执行相同,实际上是否存在字节码差异?性能方面,它们 完全 相同吗?
或者只是一个比另一个更受欢迎?哪个以及为什么?
我还没有听说过这方面的实际最佳实践,但是您经常看到当方法使用过早的 returns 时,returns true
的情况是底部,例如
public bool canReadFile(path) {
if (!fileExists(path))
return false;
if (!fileIsReadable(file))
return false;
...
return true;
}
因此,我建议您对 try/catch 个块遵循此做法。它还可以更快地查看 "expected" return 值是什么。
关于字节码,是的,确实有区别。我制作了一个快速示例程序
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
}
所以有性能差异吗?虽然我还没有测试过,但我敢打赌不会有任何明显的变化。最重要的是,这几乎不会成为您应用程序的瓶颈。
对我来说,这更多是语义和可读性问题。
如果你的 return true
在 try/catch
块之外的段的末尾,这意味着这个函数应该是 return 真值,除非在这两者之间发生了任何不好的事情中断正常流量。
相反,如果 return true
位于 try
块的末尾,则意味着只有在 try 块中的所有尝试都成功时,该函数才应该 return 为真。
这种字节码的差异或多或少可以忽略不计;我同意@kba,这更像是一个风格问题。许多 return
语句在深度嵌入 if
块内的不同位置通常会造成混淆;所以让你的代码不那么复杂是个好习惯。即
- 尽可能使用平面块而不是深度嵌入
- 将较少的状态携带到另一个代码段and/or内部
if
、for
或try
块 - 使用较少的状态和流量控制变量
- 少用像
return
或go
这样的语句,因为它们或多或少是逻辑流程的强制性改变。
希望对您有所帮助。
Return 始终设置为 false。这可能不是您所期望的情况。可能某些意外异常会导致返回错误值。所以在 catch
中返回不是一个好的标准方式