Try-with-resources example and thoughts
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Wed, 2 Jul 2014 10:21:16 +0000 (12:21 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Wed, 2 Jul 2014 10:21:16 +0000 (12:21 +0200)
Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/Main.java [new file with mode: 0644]
Allgemeines/Try-With-Resources-Java/src/de/example/tryfinally/TryWithResourcesMain.java [new file with mode: 0644]
Allgemeines/Try-With-Resources-Java/under_the_scenes.txt [new file with mode: 0644]

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
new file mode 100644 (file)
index 0000000..ef6df85
--- /dev/null
@@ -0,0 +1,81 @@
+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
new file mode 100644 (file)
index 0000000..96dc4f1
--- /dev/null
@@ -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-With-Resources-Java/under_the_scenes.txt b/Allgemeines/Try-With-Resources-Java/under_the_scenes.txt
new file mode 100644 (file)
index 0000000..203fe0c
--- /dev/null
@@ -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