Try-finally 和 try-catch 之间的区别

这两者有什么区别

try {
fooBar();
} finally {
barFoo();
}

还有

try {
fooBar();
} catch(Throwable throwable) {
barFoo(throwable); // Does something with throwable, logs it, or handles it.
}

我更喜欢第二个版本,因为它让我可以使用 Throwable。这两种变体之间是否存在逻辑上的区别或者更好的约定?

另外,是否有从 finally 子句访问异常的方法?

129621 次浏览

These are two different things:

  • The catch block is only executed if an exception is thrown in the try block.
  • The finally block is executed always after the try(-catch) block, if an exception is thrown or not.

In your example you haven't shown the third possible construct:

try {
// try to execute this statements...
}
catch( SpecificException e ) {
// if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
// if a more general exception was thrown, handle it here
}
finally {
// here you can clean things up afterwards
}

And, like @codeca says in his comment, there is no way to access the exception inside the finally block, because the finally block is executed even if there is no exception.

Of course you could declare a variable that holds the exception outside of your block and assign a value inside the catch block. Afterwards you can access this variable inside your finally block.

Throwable throwable = null;
try {
// do some stuff
}
catch( Throwable e ) {
throwable = e;
}
finally {
if( throwable != null ) {
// handle it
}
}

try is used to run a method that may throw an exception

catch is used to "catch" stop that exception

finally is used for any clean up needed from that exception being caught or not

try{
myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
myObject = null; // clean up needed from that exception being caught
}

These are not variations, they're fundamentally different things. finally is executed always, catch only when an exception occurs.

Finally block is always executed. Catch block is executed only when an exception that matches the blocks parameter is catched.

try {
statements;
} catch (exceptionType1 e1) {      // one or multiple
statements;
} catch (exceptionType2 e2) {
statements;
}
...
} finally {                                 // one or none
statements;
}
  1. All try statements must include either one catch clause or a finally clause
  2. It can have a multiple catch clauses but only one finally clause
  3. During any execution, if any errors occurs, then the Control is transferred to the appropriate Catch block and executes the statements and Finally block is executed.

No Matter what The Finally block is always executed, So in General, Finally block is used, when you have sessions, Database connections or Files or sockets are open, then the code for closing those connections will be placed. This is just to make sure in an application no memory leaks or Any other issues should not occur.

Finally and catch blocks are quite different:

  • Within the catch block you can respond to the thrown exception. This block is executed only if there is an unhandled exception and the type matches the one or is subclass of the one specified in the catch block's parameter.
  • Finally will be always executed after try and catch blocks whether there is an exception raised or not.

So

try {
//some code
}
catch (ExceptionA) {
// Only gets executed if ExceptionA
// was thrown in try block
}
catch (ExceptionB) {
// Only executed if ExceptionB was thrown in try
// and not handled by first catch block
}

differs from

try {
//some code
}
finally {
// Gets executed whether or not
// an exception was thrown in try block
}

significantly.

If you define a try block you have to define

  1. one finally block, or
  2. one or more catch blocks, or
  3. one or more catch blocks and one finally block

So the following code would be valid too:

try {
//some code
}
catch (ExceptionA) {
// Only gets executed if
// ExceptionA was thrown in try block
}
catch (ExceptionB) {
// Only executed if ExceptionB was thrown in
// try and not handled by first catch block
}
//even more catch blocks
finally {
// Gets executed whether or not an
// exception was thrown in try block
}

Even in the first form you could log it in the calling method. So there is no big advantage unless you want to do some special handling right there.

In My reasearch Finally block is always executed and it is mainly "used for the any open connections to close" and to destroy something that is running unnecessarily.

Finally and catch blocks are quite different:

Within the catch block you can respond to the thrown exception. This block is executed only if there is an unhandled exception and the type matches the one or is subclass of the one specified in the catch block's parameter. Finally will be always executed after try and catch blocks whether there is an exception raised or not.

Generally when we use any resources like streams, connections etc.. we have to close them explicitly using finally block. In the program given below we are reading data from a file using FileReader and we are closing it using finally block.

import java.io.File;
import java.io.FileReader;
import java.io.IOException;


public class ReadData_Demo {


public static void main(String args[]){
FileReader fr=null;
try{
File file=new File("file.txt");
fr = new FileReader(file);  char [] a = new char[50];
fr.read(a); // reads the content to the array
for(char c : a)
System.out.print(c); //prints the characters one by one
}catch(IOException e){
e.printStackTrace();
}
finally{
try{
fr.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
}


}

Maybe other guys like me searched for something like this.

Information from this page tutpoint

Try block will hold the statements which are going to raise exception. The catch block will hold the reference thrown from the try block and required messages are generated from catch block. Finally block is also used to close the used resources like io closing,file closing, dB closing.. In Java -9 enhanced try-with resource came up where the resources are declared outside the try..in enchanced try with resource the catch block is mandatory