From: gu.martinm@gmail.com Date: Wed, 2 Jul 2014 10:30:47 +0000 (+0200) Subject: Try-Finally and Try-With-Resources (with some thoughts) X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=fb3b164a926c605200ec72643ada90fbdc17a28f;p=JavaForFun Try-Finally and Try-With-Resources (with some thoughts) --- diff --git a/Allgemeines/Try-Finally-Try-With-Resources-Java/src/de/example/tryfinally/TryFinallyMain.java b/Allgemeines/Try-Finally-Try-With-Resources-Java/src/de/example/tryfinally/TryFinallyMain.java new file mode 100644 index 0000000..f92ad98 --- /dev/null +++ b/Allgemeines/Try-Finally-Try-With-Resources-Java/src/de/example/tryfinally/TryFinallyMain.java @@ -0,0 +1,81 @@ +package de.example.tryfinally; + +public class TryFinallyMain { + static String result; + + public static void main(final String[] args) { + System.out.println("Calling go"); + final String st = returnAndFinally(); + System.out.println("Back from go: " + st); + System.out.println("Surprise!! " + result); + + try { + System.out.println(noCatchAndFinally()); + } catch (final Exception e) { + System.out.println("Second catch."); + e.printStackTrace(); + } + } + + public static String returnAndFinally() { + result = "NOK"; + + try { + messingAround(); + return result; + } + catch (final Exception ex) { + System.out.println("Entered catch: " + result); + result = "OK"; + //This is the return statement that this method will execute in case of any Exception class or subclass is thrown. + return result; + } + finally { + //You will not see FINALLY in the "Back from go:" statement. + //From stackoverflow: + //http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement. + // * Code before return statement is executed + // * Expression in return statement is evaluated + // * finally block is executed + // * Result evaluated in step 2 is returned + + result = "FINALLY"; + System.out.println("Entered finally: " + result); + //NEVER USE return in finally block because you can loose the stack if some exception is thrown from the try block!!! + //You finish with this return instead of the previous one. + //http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java + //return result; + } + } + + public static void messingAround() throws Exception { + throw(new Exception()); + } + + + public static String noCatchAndFinally() throws Exception { + try { + messingAround(); + return "You will not see me"; + } + finally { + try + { + //Catching this exception does not swallow the previous one (if there was one) + messingAroundReturns(); + } + catch (final Exception e) { + System.out.println("First catch."); + e.printStackTrace(); + } + //NEVER USE return in finally block because you can loose the stack if some exception is thrown from the try block!!! + //http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java + // return + // "Do not do this. You are loosing the exception thrown by messingAround method!!!"; + } + } + + public static void messingAroundReturns() throws Exception { + throw(new Exception()); + } +} diff --git a/Allgemeines/Try-Finally-Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java b/Allgemeines/Try-Finally-Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java new file mode 100644 index 0000000..96dc4f1 --- /dev/null +++ b/Allgemeines/Try-Finally-Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java @@ -0,0 +1,65 @@ +package de.example.tryfinally; + +public class TryWithResourcesMain { + + public static void main(final String[] args) { + System.out.println("BEGIN FIRST EXAMPLE"); + System.out.flush(); + + try (final ResourceFirst resourceOne = new ResourceFirst(); + final ResourceSecond resourceTwo = new ResourceSecond()) + { + resourceTwo.doSomething(); + resourceOne.doSomething(); + } catch (final Exception e) { + System.out.println("Exception from some resource: "); + System.out.flush(); + e.printStackTrace(); + System.out.flush(); + } + + System.out.println("END FIRST EXAMPLE"); + System.out.flush(); + + } + + public static class ResourceFirst implements AutoCloseable + { + public ResourceFirst() { + + } + + public void doSomething() { + System.out.println("ResourceFirst: doSomething"); + System.out.flush(); + throw new RuntimeException("ResourceFirst doSomething RuntimeException!!!"); + } + + @Override + public void close() throws Exception { + System.out.println("I am the close of ResourceFirst"); + System.out.flush(); + throw new Exception("ResourceFirst close Exception!!!"); + } + } + + + public static class ResourceSecond implements AutoCloseable + { + public ResourceSecond() { + + } + + public void doSomething() { + System.out.println("ResourceSecond: doSomething"); + System.out.flush(); + } + + @Override + public void close() throws Exception { + System.out.println("I am the close of ResourceSecond"); + System.out.flush(); + throw new Exception("ResourceSecond close Exception!!!"); + } + } +} diff --git a/Allgemeines/Try-Finally-Try-With-Resources-Java/under_the_scenes.txt b/Allgemeines/Try-Finally-Try-With-Resources-Java/under_the_scenes.txt new file mode 100644 index 0000000..203fe0c --- /dev/null +++ b/Allgemeines/Try-Finally-Try-With-Resources-Java/under_the_scenes.txt @@ -0,0 +1,109 @@ +output from example: + +BEGIN FIRST EXAMPLE +ResourceSecond: doSomething +ResourceFirst: doSomething +I am the close of ResourceSecond +I am the close of ResourceFirst +Exception from some resource: +java.lang.RuntimeException: ResourceFirst doSomething RuntimeException!!! + at de.example.tryfinally.TryWithResourcesMain$ResourceFirst.doSomething(TryWithResourcesMain.java:35) + at de.example.tryfinally.TryWithResourcesMain.main(TryWithResourcesMain.java:13) + Suppressed: java.lang.Exception: ResourceSecond close Exception!!! + at de.example.tryfinally.TryWithResourcesMain$ResourceSecond.close(TryWithResourcesMain.java:62) + at de.example.tryfinally.TryWithResourcesMain.main(TryWithResourcesMain.java:14) + Suppressed: java.lang.Exception: ResourceFirst close Exception!!! + at de.example.tryfinally.TryWithResourcesMain$ResourceFirst.close(TryWithResourcesMain.java:42) + at de.example.tryfinally.TryWithResourcesMain.main(TryWithResourcesMain.java:14) +END FIRST EXAMPLE + + + +So, it is nicer than C# because you can see the hidden exceptions. +As in C# it keeps running the close methods even if some of them throw exception!!! + +SO, THE BEST WAY TO CLOSE DEVICES IN JAVA IS USING TRY-WITH-RESOURCES!!!!! +OTHERWISE YOU ARE GOING TO WRITE LOADS OF CODE IF YOU WANT TO DO THE SAME!!!! + + +1 .BEFORE JAVA 7; some Java SMART developers (the most of them do not even know they have to release +resources...) always did something like this: + + MyResourceOne resourceOne; + MyResourceTwo resourceTwo; + try { + *** WHATEVER YOU DO WITH YOUR RESOURCES *** + } finally { + if (resourceOne != null) { + closeQuietly(resourceOne); + } + if (resourceTwo != null) { + closeQuietly(resourceTwo); + } + } + + private void closeQuietly(final Closeable resource ) { + try { + if (resource != null) { + resource.close(); + } + } catch(final IOException e) { + logger.error( "Exception while closing resource ", e); + } + } + +IMHO swallowing exceptions is not nice... Perhaps for some particular things it could be interesting +but in general NEVER SWALLOW EXCEPTIONS LIKE THAT!!! + + +2. Other ways I have seen: + + MyResourceOne resourceOne; + MyResourceTwo resourceTwo; + try { + *** WHATEVER YOU DO WITH YOUR RESOURCES *** + } finally { + if (resourceOne != null) { + resourceOne.close(); + } + if (resourceTwo != null) { + resourceTwo.close(); + } + } + +The problem with this way is, if resourceOne.close() throws exception I am not going to call resourceTwo.close() :( +Even if this guy says the opposite: http://stackoverflow.com/a/18496449 (IMHO THAT ANSWER SUCKS!!!!) + + +3. Before Java 1.7 this was the only "nice" way (IMHO) + + + MyResourceOne resourceOne = new MyResourceOne(); + + try { + *** WHATEVER YOU DO WITH YOUR RESOURCE ONE *** + MyResourceTwo resourceTwo = new MyResourceTwo(); + try { + *** WHATEVER YOU DO WITH YOUR RESOURCE TWO *** + } finally { + resourceTwo.close(); + } + } finally { + resourceOne.close(); + } +It is really close to RAII C++. I am always closing resources and I do not swallow exceptions :) +You could achieve this solution through using multiple methods (instead of one with nested try/finally blocks); +for example one nice solution would be with the Execute Around idiom and closures. + +IMHO since Java 1.7 and the TRY-WITH-RESOURCES there is no doubt what everybody should use. Besides, we +do not need anymore the Execute Around idiom AFAIU. +But perhaps with the Execute Around idiom the code in some case could be clearer. For simple things I guess +the best is the TRY-WITH-RESOURCE; for complicated ones (see Spring JDBC) the Exceute Around idiom would be better +(I guess) + +http://stackoverflow.com/questions/12552863/correct-idiom-for-managing-multiple-chained-resources-in-try-with-resources-bloc +http://stackoverflow.com/a/12665271 <---- This answer is the best. I do not wonder that guy comes from C++ :) +http://stackoverflow.com/a/18496449 <---- This answer sucks. + +http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom +http://stackoverflow.com/questions/481446/throws-exception-in-finally-blocks <--- Swallowing exceptions... :/ \ No newline at end of file diff --git a/Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/Main.java b/Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/Main.java deleted file mode 100644 index ef6df85..0000000 --- a/Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/Main.java +++ /dev/null @@ -1,81 +0,0 @@ -package de.example.tryfinally; - -public class Main { - static String result; - - public static void main(final String[] args) { - System.out.println("Calling go"); - final String st = returnAndFinally(); - System.out.println("Back from go: " + st); - System.out.println("Surprise!! " + result); - - try { - System.out.println(noCatchAndFinally()); - } catch (final Exception e) { - System.out.println("Second catch."); - e.printStackTrace(); - } - } - - public static String returnAndFinally() { - result = "NOK"; - - try { - messingAround(); - return result; - } - catch (final Exception ex) { - System.out.println("Entered catch: " + result); - result = "OK"; - //This is the return statement that this method will execute in case of any Exception class or subclass is thrown. - return result; - } - finally { - //You will not see FINALLY in the "Back from go:" statement. - //From stackoverflow: - //http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement. - // * Code before return statement is executed - // * Expression in return statement is evaluated - // * finally block is executed - // * Result evaluated in step 2 is returned - - result = "FINALLY"; - System.out.println("Entered finally: " + result); - //NEVER USE return in finally block because you can loose the stack if some exception is thrown from the try block!!! - //You finish with this return instead of the previous one. - //http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java - //return result; - } - } - - public static void messingAround() throws Exception { - throw(new Exception()); - } - - - public static String noCatchAndFinally() throws Exception { - try { - messingAround(); - return "You will not see me"; - } - finally { - try - { - //Catching this exception does not swallow the previous one (if there was one) - messingAroundReturns(); - } - catch (final Exception e) { - System.out.println("First catch."); - e.printStackTrace(); - } - //NEVER USE return in finally block because you can loose the stack if some exception is thrown from the try block!!! - //http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java - // return - // "Do not do this. You are loosing the exception thrown by messingAround method!!!"; - } - } - - public static void messingAroundReturns() throws Exception { - throw(new Exception()); - } -} diff --git a/Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java b/Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java deleted file mode 100644 index 96dc4f1..0000000 --- a/Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java +++ /dev/null @@ -1,65 +0,0 @@ -package de.example.tryfinally; - -public class TryWithResourcesMain { - - public static void main(final String[] args) { - System.out.println("BEGIN FIRST EXAMPLE"); - System.out.flush(); - - try (final ResourceFirst resourceOne = new ResourceFirst(); - final ResourceSecond resourceTwo = new ResourceSecond()) - { - resourceTwo.doSomething(); - resourceOne.doSomething(); - } catch (final Exception e) { - System.out.println("Exception from some resource: "); - System.out.flush(); - e.printStackTrace(); - System.out.flush(); - } - - System.out.println("END FIRST EXAMPLE"); - System.out.flush(); - - } - - public static class ResourceFirst implements AutoCloseable - { - public ResourceFirst() { - - } - - public void doSomething() { - System.out.println("ResourceFirst: doSomething"); - System.out.flush(); - throw new RuntimeException("ResourceFirst doSomething RuntimeException!!!"); - } - - @Override - public void close() throws Exception { - System.out.println("I am the close of ResourceFirst"); - System.out.flush(); - throw new Exception("ResourceFirst close Exception!!!"); - } - } - - - public static class ResourceSecond implements AutoCloseable - { - public ResourceSecond() { - - } - - public void doSomething() { - System.out.println("ResourceSecond: doSomething"); - System.out.flush(); - } - - @Override - public void close() throws Exception { - System.out.println("I am the close of ResourceSecond"); - System.out.flush(); - throw new Exception("ResourceSecond close Exception!!!"); - } - } -} diff --git a/Allgemeines/Try-With-Resources-Java/under_the_scenes.txt b/Allgemeines/Try-With-Resources-Java/under_the_scenes.txt deleted file mode 100644 index 203fe0c..0000000 --- a/Allgemeines/Try-With-Resources-Java/under_the_scenes.txt +++ /dev/null @@ -1,109 +0,0 @@ -output from example: - -BEGIN FIRST EXAMPLE -ResourceSecond: doSomething -ResourceFirst: doSomething -I am the close of ResourceSecond -I am the close of ResourceFirst -Exception from some resource: -java.lang.RuntimeException: ResourceFirst doSomething RuntimeException!!! - at de.example.tryfinally.TryWithResourcesMain$ResourceFirst.doSomething(TryWithResourcesMain.java:35) - at de.example.tryfinally.TryWithResourcesMain.main(TryWithResourcesMain.java:13) - Suppressed: java.lang.Exception: ResourceSecond close Exception!!! - at de.example.tryfinally.TryWithResourcesMain$ResourceSecond.close(TryWithResourcesMain.java:62) - at de.example.tryfinally.TryWithResourcesMain.main(TryWithResourcesMain.java:14) - Suppressed: java.lang.Exception: ResourceFirst close Exception!!! - at de.example.tryfinally.TryWithResourcesMain$ResourceFirst.close(TryWithResourcesMain.java:42) - at de.example.tryfinally.TryWithResourcesMain.main(TryWithResourcesMain.java:14) -END FIRST EXAMPLE - - - -So, it is nicer than C# because you can see the hidden exceptions. -As in C# it keeps running the close methods even if some of them throw exception!!! - -SO, THE BEST WAY TO CLOSE DEVICES IN JAVA IS USING TRY-WITH-RESOURCES!!!!! -OTHERWISE YOU ARE GOING TO WRITE LOADS OF CODE IF YOU WANT TO DO THE SAME!!!! - - -1 .BEFORE JAVA 7; some Java SMART developers (the most of them do not even know they have to release -resources...) always did something like this: - - MyResourceOne resourceOne; - MyResourceTwo resourceTwo; - try { - *** WHATEVER YOU DO WITH YOUR RESOURCES *** - } finally { - if (resourceOne != null) { - closeQuietly(resourceOne); - } - if (resourceTwo != null) { - closeQuietly(resourceTwo); - } - } - - private void closeQuietly(final Closeable resource ) { - try { - if (resource != null) { - resource.close(); - } - } catch(final IOException e) { - logger.error( "Exception while closing resource ", e); - } - } - -IMHO swallowing exceptions is not nice... Perhaps for some particular things it could be interesting -but in general NEVER SWALLOW EXCEPTIONS LIKE THAT!!! - - -2. Other ways I have seen: - - MyResourceOne resourceOne; - MyResourceTwo resourceTwo; - try { - *** WHATEVER YOU DO WITH YOUR RESOURCES *** - } finally { - if (resourceOne != null) { - resourceOne.close(); - } - if (resourceTwo != null) { - resourceTwo.close(); - } - } - -The problem with this way is, if resourceOne.close() throws exception I am not going to call resourceTwo.close() :( -Even if this guy says the opposite: http://stackoverflow.com/a/18496449 (IMHO THAT ANSWER SUCKS!!!!) - - -3. Before Java 1.7 this was the only "nice" way (IMHO) - - - MyResourceOne resourceOne = new MyResourceOne(); - - try { - *** WHATEVER YOU DO WITH YOUR RESOURCE ONE *** - MyResourceTwo resourceTwo = new MyResourceTwo(); - try { - *** WHATEVER YOU DO WITH YOUR RESOURCE TWO *** - } finally { - resourceTwo.close(); - } - } finally { - resourceOne.close(); - } -It is really close to RAII C++. I am always closing resources and I do not swallow exceptions :) -You could achieve this solution through using multiple methods (instead of one with nested try/finally blocks); -for example one nice solution would be with the Execute Around idiom and closures. - -IMHO since Java 1.7 and the TRY-WITH-RESOURCES there is no doubt what everybody should use. Besides, we -do not need anymore the Execute Around idiom AFAIU. -But perhaps with the Execute Around idiom the code in some case could be clearer. For simple things I guess -the best is the TRY-WITH-RESOURCE; for complicated ones (see Spring JDBC) the Exceute Around idiom would be better -(I guess) - -http://stackoverflow.com/questions/12552863/correct-idiom-for-managing-multiple-chained-resources-in-try-with-resources-bloc -http://stackoverflow.com/a/12665271 <---- This answer is the best. I do not wonder that guy comes from C++ :) -http://stackoverflow.com/a/18496449 <---- This answer sucks. - -http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom -http://stackoverflow.com/questions/481446/throws-exception-in-finally-blocks <--- Swallowing exceptions... :/ \ No newline at end of file diff --git a/Allgemeines/TryCatchFinally/src/de/example/tryfinally/Main.java b/Allgemeines/TryCatchFinally/src/de/example/tryfinally/Main.java deleted file mode 100644 index ef6df85..0000000 --- a/Allgemeines/TryCatchFinally/src/de/example/tryfinally/Main.java +++ /dev/null @@ -1,81 +0,0 @@ -package de.example.tryfinally; - -public class Main { - static String result; - - public static void main(final String[] args) { - System.out.println("Calling go"); - final String st = returnAndFinally(); - System.out.println("Back from go: " + st); - System.out.println("Surprise!! " + result); - - try { - System.out.println(noCatchAndFinally()); - } catch (final Exception e) { - System.out.println("Second catch."); - e.printStackTrace(); - } - } - - public static String returnAndFinally() { - result = "NOK"; - - try { - messingAround(); - return result; - } - catch (final Exception ex) { - System.out.println("Entered catch: " + result); - result = "OK"; - //This is the return statement that this method will execute in case of any Exception class or subclass is thrown. - return result; - } - finally { - //You will not see FINALLY in the "Back from go:" statement. - //From stackoverflow: - //http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement. - // * Code before return statement is executed - // * Expression in return statement is evaluated - // * finally block is executed - // * Result evaluated in step 2 is returned - - result = "FINALLY"; - System.out.println("Entered finally: " + result); - //NEVER USE return in finally block because you can loose the stack if some exception is thrown from the try block!!! - //You finish with this return instead of the previous one. - //http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java - //return result; - } - } - - public static void messingAround() throws Exception { - throw(new Exception()); - } - - - public static String noCatchAndFinally() throws Exception { - try { - messingAround(); - return "You will not see me"; - } - finally { - try - { - //Catching this exception does not swallow the previous one (if there was one) - messingAroundReturns(); - } - catch (final Exception e) { - System.out.println("First catch."); - e.printStackTrace(); - } - //NEVER USE return in finally block because you can loose the stack if some exception is thrown from the try block!!! - //http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java - // return - // "Do not do this. You are loosing the exception thrown by messingAround method!!!"; - } - } - - public static void messingAroundReturns() throws Exception { - throw(new Exception()); - } -}