Java:catch 的含义(最终 SomeException e)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3516816/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:11:52  来源:igfitidea点击:

Java: Meaning of catch (final SomeException e)?

javaexceptionexception-handlingfinal

提问by PlagueHammer

What does finaldo in the following Java expression?

是什么final在以下Java表达式吗?

catch (final SomeExceptionType e)

回答by Edwin Buck

It basically means:

它基本上意味着:

Catch "SomeExceptionType" into the variable "e" with the promise that we won't assign a different exception to "e" during the processing of the exception.

将“SomeExceptionType”捕获到变量“e”中,并承诺在处理异常期间不会将不同的异常分配给“e”。

Mostly this is overkill, as if I'm catching an exception into a temporary variable name (e only is valid for the exception handling block), I don't have to police myself so strictly as to not trust myself to assign a different (possibly created) exception to the same variable name.

大多数情况下,这有点矫枉过正,好像我将异常捕获到一个临时变量名中(e 仅对异常处理块有效),我不必如此严格地监管自己,以至于不相信自己会分配一个不同的(可能已创建)相同变量名称的异常。

That said, perhaps this block is heavily maintained by a team of different-minded individuals, and one just wanted to be VERY sure that e was the original captured exception.

也就是说,也许这个块是由一群思想不同的人大量维护的,一个人只是想非常确定 e 是原始捕获的异常。

---- Edited in response to commentary ----

---- 为回应评论而编辑----

I can't think of a really excellent reason to do this. Since "e" is not a member (static or otherwise) the name "e" won't be used by the class file post-compilation. Another way of stating this is that when you enter the exception handling block of JVM bytecode, the object won't be assigned to any of the member names accessible by the JVM processing frame, it will be pushed to the internal processing stack of the Thread's current frame.

我想不出一个非常好的理由来做这件事。由于“e”不是成员(静态或其他),因此编译后的类文件不会使用名称“e”。另一种说法是,当您进入JVM字节码的异常处理块时,该对象不会被分配给JVM处理帧可访问的任何成员名称,而是会被推送到线程的内部处理堆栈当前帧。

Even if two threads had access to the same Object, each thread would have it's own frame, so the compiler removed "e" name from one frame's internal stack couldn't be altered by the other thread.

即使两个线程可以访问同一个对象,每个线程也会有自己的框架,因此编译器从一个框架的内部堆栈中删除了“e”名称,另一个线程无法更改。

With that in mind, the only benefit of declaring "e" final is to make sure that future coders don't accidentally set "e" after entering the block. Perhaps they meant to make the code more robust in a multi-threaded environment, but temporary variables (those with names that only are valid in the block) don't have names post-compilation, they are pushed onto the frame's stack.

考虑到这一点,将“e”声明为 final 的唯一好处是确保未来的编码人员不会在进入块后意外设置“e”。也许他们的目的是使代码在多线程环境中更加健壮,但是临时变量(名称仅在块中有效的变量)在编译后没有名称,它们被推送到框架的堆栈中。

That's why

这就是为什么

public int safe() {
  int x = 5;
  x = x + 5;
  return x;
}

is generally regarded as thread safe, because it does this (in pseudo bytecode)

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

(In the thread's current frame)
push 5
push 5
add integers
return

While this isn't thread safe

虽然这不是线程安全的

int x = 5;

public void unsafe() {
  x = 5;
  x = x + 5;
  return x;
}

because it does this

因为它这样做

(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

The latter bytecode makes it apparent that interleaving two threads creates thread-to-thread communications using member x an an intermediary, while the first block of code cannot have any inter-thread communication because there's no intermediary.

后一个字节码清楚地表明,交错两个线程使用成员 x 作为中介创建线程到线程的通信,而第一个代码块不能进行任何线程间通信,因为没有中介。

回答by Tom Hawtin - tackline

Currently it means finalmuch the same as any local variable, other than it is always "definitely assigned".

目前,它final与任何局部变量的含义大致相同,只是它始终是“明确分配的”。

In recent JDK7 builds, a Project Coin language changeallows it to indicate a degree of implicit static typing is going on. A single catchcan catch a number of different checked exceptions by a common base type, and rethrow with the enclosing context only having catch or declare those exceptions that could (statically speaking) be thrown within the try. (See the link for a better explanation.)

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

回答by Austin D

The question, "What does finaldo?" is addressed in other answers to this question, and here, here, and here. But in the context of a try-catchblock, the Java Language Specification (JLS) §4.12.4 states(emphasis my own):

问题是“做final什么?” 已在此问题的其他答案以及此处此处此处解决。但是在try-catch块的上下文中,Java 语言规范 (JLS) §4.12.4 指出(强调我自己的):

  • A resource of a try-with-resources statement(§14.20.3) and an exception parameter of a multi-catch clause(§14.20) are implicitly declared final.
  • An exception parameter of a uni-catch clause(§14.20) may be effectively final instead of being explicitly declared final. Such a parameter is never implicitly declared final.
  • 一个的资源的尝试,与资源的语句(§14.20.3)和一个异常参数多catch子句(§14.20)被隐式声明为final
  • uni-catch 子句14.20 节)的异常参数可能实际上是最终的,而不是明确声明为最终的。这样的参数永远不会被隐式声明为 final

In a multi-catch clause:

在 multi-catch 子句中

Adding the finalkeyword to a multi-catch clausesimply makes explicit the fact that the variableis implicitly final. In general, whenever the finalkeyword conveys additional information that helps make your code more readable/maintainable, use it.

final关键字添加到multi-catch 子句中只会明确表明 thevariable是隐式 final的事实。一般来说,只要final关键字传达了有助于使您的代码更具可读性/可维护性的附加信息,就使用它。

In a uni-catch clause

在 uni-catch 子句中

On the other hand, the exception parameter in a uni-catch clauseis neverimplicitly final. So, using the finalkeyword to a uni-catch clauseprevents something like the following from happening:

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

try {
     throw new Exception();
catch (Exception e){
    e = null;
    e.printStackTrace(); //throws a NullPointerException
}

The issue is obvious in this simple example. But two cases may be less obvious and warrant the use of final:

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

  1. If the catch block is more complicated, accidental reassignment is possible. (Although, if the catch block is complicated, you're probably doing it wrong.)
  2. To prevent issues caused during code maintenance. Adding finalto the exception variable will ensure reassignment is caught at compilation, rather than Runtime
  1. 如果 catch 块更复杂,则可能会意外重新分配。(虽然,如果 catch 块很复杂,你可能做错了。)
  2. 防止代码维护过程中出现问题。添加final到异常变量将确保在编译捕获重新分配,而不是运行时

As a general rule of thumb, use the finalkeyword in a uni-catch clausein the same way you would use the finalkeyword for a method parameter:

作为一般经验法则,finaluni-catch 子句中使用final关键字的方式与将关键字用于方法参数的方式相同

JLS§4.12.4: Declaring a variable final can serve as useful documentation that its value will not change and can help avoid programming errors.

JLS§4.12.4:声明一个变量 final 可以作为有用的文档,说明它的值不会改变,并且可以帮助避免编程错误。

回答by Thorbj?rn Ravn Andersen

The finalkeyword on variables means that the variable can only be assigned once, and as the assignment here is being done by the compiler it means that the variable cannot be changed later in the code.

final该变量只能分配一次,这里的分配是由编译器完成这意味着该变量不能在后面的代码改变了变量的平均值关键字。

This is an important property as it means to the maintainer that this particular variable will have this particular value everywhere it is used and it is not necessary to keep track of where it changes. This is recognized to be so useful that the "Clean up" action in Eclipse allows for adding "final" whereever it possibly can, and I believe that what you see is the resultof such an automatic clean up, because most human programmers would keep the catch-block short so such an indication is not needed.

这是一个重要的属性,因为它对维护者来说意味着这个特定的变量在任何使用它的地方都将具有这个特定的值,并且没有必要跟踪它的变化。这被认为非常有用,以至于 Eclipse 中的“清理”操作允许在任何可能的地方添加“最终”,我相信您看到的是这种自动清理的结果,因为大多数人类程序员都会保留catch-block 短路所以不需要这样的指示。