Edw*_*uck 32

它基本上意味着:

将"SomeExceptionType"捕获到变量"e"中,并保证在处理异常期间我们不会为"e"分配不同的异常.

大多数情况下这都是矫枉过正,好像我正在将一个异常捕获到一个临时变量名中(e只对异常处理块有效),我不必严格警告自己,不要相信自己指定一个不同的(可能已创建)相同变量名的异常.

也就是说,也许这个区块由一群心胸不同的人大量维护,而且只是想要非常确定e是原始捕获的异常.

----编辑回应评论----

我无法想到这样做的一个非常好的理由.由于"e"不是成员(静态或其他),因此编译后的类文件不会使用名称"e".说明这一点的另一种方法是,当您输入JVM字节码的异常处理块时,该对象将不会被分配给JVM处理框架可访问的任何成员名称,它将被推送到Thread的内部处理堆栈中.当前帧.

即使两个线程可以访问同一个Object,每个线程都有自己的帧,因此编译器从一个帧的内部堆栈中删除"e"名称不能被另一个线程更改.

考虑到这一点,宣布"e"final的唯一好处是确保未来的编码人员在进入区块后不会意外设置"e".也许它们意味着在多线程环境中使代码更加健壮,但临时变量(名称仅在块中有效的那些变量)在编译后没有名称,它们被推送到帧的堆栈中.

这就是为什么

public int safe() {
  int x = 5;
  x = x + 5;
  return x;
}
Run Code Online (Sandbox Code Playgroud)

通常被认为是线程安全的,因为它这样做(伪字节码)

(In the thread's current frame)
push 5
push 5
add integers
return
Run Code Online (Sandbox Code Playgroud)

虽然这不是线程安全的

int x = 5;

public void unsafe() {
  x = 5;
  x = x + 5;
  return x;
}
Run Code Online (Sandbox Code Playgroud)

因为它做到了这一点

(in the thread's current frame)
push "this"
push 5
set member x
push "this"
get member x
push 5
add integer
set member x
get member x
return
Run Code Online (Sandbox Code Playgroud)

后一个字节码显然交错两个线程使用成员x和中间件创建线程到线程的通信,而第一个代码块不能有任何线程间通信,因为没有中间件.

  • @Nocturne:通过标记"e"final,作者禁止重新分配"e"以引用catch块中的不同对象.它是一种维护安全机制,而不是以这种方式使用的并发辅助.在代码编译期间将尝试重新分配"e". (6认同)
  • 我怀疑`final`可能只是自动重构的产物.我无法想象究竟是哪种重构可能导致这种情况,但重构尽可能多地留下最终结果是很常见的. (5认同)
  • @Nocturne:多线程与它无关.由于变量"e"是处理程序块的本地变量,因此永远无法从其他线程访问它.我认为如果你有一个冗长而复杂的处理程序块可能会有点有用 - 但在这种情况下,你可能无论如何都做错了. (4认同)

Tom*_*ine 11

目前它意味着final与任何局部变量大致相同,除了它总是"明确分配".

在最近的JDK7版本中,Project Coin语言更改允许它指示一定程度的隐式静态类型正在进行.单个catch可以通过公共基类型捕获许多不同的已检查异常,并且重新抛出包含上下文仅具有catch或声明可以(静态地说)被抛出的异常try.(有关更好的解释,请参阅链接.)


Aus*_*n D 5

问题是“做final什么?” 在这个问题的其他答案中,在这里在这里在这里都得到解决。但是在try-catch块的上下文中,Java语言规范(JLS)§4.12.4声明(强调我自己):

  • 一个的资源的尝试,与资源的语句(§14.20.3)和一个异常参数多catch子句(§14.20)被隐式声明为final
  • uni-catch子句的异常参数( 14.20节)可以有效地是final,而不是被明确声明为final。此类参数永远不会隐式声明为final

在多捕获子句中

final关键字添加到multi-catch子句中只会使variable隐式最终的事实变得明确。通常,每当final关键字传达有助于使您的代码更具可读性/可维护性的其他信息时,请使用它。

在单捕获子句中

在另一方面,在异常参数UNI-catch子句永远隐含决赛。因此,finaluni-catch子句使用关键字可以防止发生以下情况:

try {
     throw new Exception();
catch (Exception e){
    e = null;
    e.printStackTrace(); //throws a NullPointerException
}
Run Code Online (Sandbox Code Playgroud)

在这个简单的示例中,问题很明显。但是有两种情况可能不太明显,因此可以使用final

  1. 如果挡块更加复杂,则可能会意外重新分配。(尽管,如果catch块很复杂,您可能做错了。)
  2. 为了防止在代码维护期间引起问题。添加final到异常变量将确保在编译而不是运行时捕获重新分配

根据经验,finaluni-catch子句 中使用final关键字的方式与在方法参数中使用关键字的方式相同

JLS§4.12.4:声明变量final可作为有用的文档,说明其值不会更改,并有助于避免编程错误。