From fd8e9579b80e25f1887ab18494bd0908e42a3655 Mon Sep 17 00:00:00 2001 From: "Dr. Martin Goik" <goik@hdm-stuttgart.de> Date: Thu, 20 Jan 2022 21:43:22 +0100 Subject: [PATCH] AutoCloseable, Exercise understanding initializations in try ... catch --- Doc/Sd1/errorHandling.xml | 64 ++++++++++++++++++---- Doc/Sd1/workingWithNumbers.xml | 99 ++++++++++++++++++++++++++++------ 2 files changed, 139 insertions(+), 24 deletions(-) diff --git a/Doc/Sd1/errorHandling.xml b/Doc/Sd1/errorHandling.xml index 405bd8b4f..bd8e2d614 100644 --- a/Doc/Sd1/errorHandling.xml +++ b/Doc/Sd1/errorHandling.xml @@ -336,7 +336,7 @@ try { xml:id="sd1_errorHandling_fig_tryWithResources-2-co"/> = new Scanner(System.in)) { ... // Something may fail }<co linkends="sd1_errorHandling_fig_tryWithResources-3" - xml:id="sd1_errorHandling_fig_tryWithResources-3-co"/></programlisting> + xml:id="sd1_errorHandling_fig_tryWithResources-3-co"/> // implicitly calling scanner.close()</programlisting> <calloutlist> <callout arearefs="sd1_errorHandling_fig_tryWithResources-1-co" @@ -360,6 +360,56 @@ try { </callout> </calloutlist> </figure> + + <figure xml:id="sd1_errorHandling_fig_ScannerAutoCloseable"> + <title>Scanner implementing <classname + xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/AutoCloseable.html">AutoCloseable</classname></title> + + <informaltable border="0"> + <tr> + <td valign="top"><programlisting language="java">public class Scanner + implements AutoCloseable <co + linkends="sd1_errorHandlingAutoCloseablePromise-1" + xml:id="sd1_errorHandlingAutoCloseablePromise-1-co"/>, ... { + + ... + + public void close() {...} <co + linkends="sd1_errorHandlingAutoCloseablePromise-2" + xml:id="sd1_errorHandlingAutoCloseablePromise-2-co"/> + +}</programlisting></td> + + <td valign="top"><programlisting language="java">Interface AutoCloseable { + public void close(); // Signature, no + // implementation +}</programlisting></td> + </tr> + </informaltable> + + <calloutlist> + <callout arearefs="sd1_errorHandlingAutoCloseablePromise-1-co" + xml:id="sd1_errorHandlingAutoCloseablePromise-1"> + <para>Promise to implement all methods being declared in <classname + xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/AutoCloseable.html">AutoCloseable</classname>.</para> + </callout> + + <callout arearefs="sd1_errorHandlingAutoCloseablePromise-2-co" + xml:id="sd1_errorHandlingAutoCloseablePromise-2"> + <para>Actually implementing a <methodname>close()</methodname> + method.</para> + </callout> + </calloutlist> + </figure> + + <figure xml:id="sd1_errorHandling_fig_tryWithResourcesString"> + <title>No <methodname>close()</methodname> method in e.g. + <classname>class</classname> String</title> + + <programlisting language="java">try (final String s = new String()) { // Error: Required type: AutoCloseable; Provided: String + ... +}</programlisting> + </figure> </section> <section xml:id="sd1_errorhandling_sect_classException"> @@ -437,11 +487,9 @@ public class StackTrace { new <link xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/File.html#%3Cinit%3E(java.lang.String)">File("test.txt"))</link>; } catch(Exception e) { System.err.println("General error"); -} catch (<emphasis role="red" - xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html">IOException e</emphasis>) { +} catch (<emphasis role="red">IOException e</emphasis>) { System.err.println( "IO error"); -} catch(<emphasis role="red" - xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/FileNotFoundException.html">FileNotFoundException e</emphasis>) { +} catch(<emphasis role="red">FileNotFoundException e</emphasis>) { System.err.println("File not found"); }</programlisting></td> @@ -457,11 +505,9 @@ public class StackTrace { <figure xml:id="sd1_errorHandling_fig_implementCardinalSimple"> <title>Implementing <methodname>convert</methodname></title> - <programlisting language="java">/** - * Translate {"one", "two", "three"} to {"first", "second", "third"} + <programlisting language="java">/* Translate {"one", "two", "three"} to {"first", "second", "third"} * @param input The input String to be translated. - * @return See above explanation. - */ + * @return See above explanation. */ static public String convert(final String input) { switch (input) { case "one": return "first"; diff --git a/Doc/Sd1/workingWithNumbers.xml b/Doc/Sd1/workingWithNumbers.xml index 2ba8a9b41..51157282d 100644 --- a/Doc/Sd1/workingWithNumbers.xml +++ b/Doc/Sd1/workingWithNumbers.xml @@ -324,16 +324,17 @@ Double d = intValue;</programlisting> <colgroup width="35%"/> <tr> - <td valign="top"><programlisting language="java">String userInput = "dummyValue"; + <td valign="top"><programlisting language="java">String userInput = null; try (final Scanner scanner = new Scanner(System.in)){ System.out.print("Enter an integer:"); userInput = scanner.nextLine(); + final int value = Integer.parseInt(userInput); + System.out.println("You entered " + value); } catch (final NumberFormatException e) { - System.out.println("Sorry, but '" + - userInput + "' is not an integer."); + System.out.println("Error: No integer value"); }</programlisting></td> <td valign="top"><screen>Enter an integer:-34 @@ -346,14 +347,14 @@ not an integer.</screen></td> <qandaset defaultlabel="qanda" xml:id="sd1_numbers_qanda_whyDummyString"> <title>Why using <code language="java">String userInput = - "dummyValue"</code>?</title> + null</code>?</title> <qandadiv> <qandaentry> <question> <para>The former listing initializes the <code language="java">userInput</code> variable using a default value - <code language="java">"dummyValue"</code>. Why is that?</para> + <code language="java">null</code>. Why is that?</para> <orderedlist> <listitem> @@ -379,26 +380,35 @@ not an integer.</screen></td> </orderedlist> <para>So the dummy assignment <code language="java">String - userInput = "dummyValue"</code> seems to be redundant. Is that + userInput = null</code> seems to be redundant. Is that true?</para> </question> <answer> <para>Actually the <xref linkend="glo_Java"/> compiler is not clever enough analyzing the <code language="java">try {...}</code> - block. It cannot detect the impossibility of an uninitialized - <code language="java">userInput</code> variable inside the <code - language="java">catch {...}</code> clause.</para> + block. The catch clause can only be reached by inadequate user + input causing the <methodname>parseInt(...)</methodname> method. + In particular the <methodname>nextLine(...)</methodname> being + unable to throw a <classname + xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/NumberFormatException.html">NumberFormatException</classname> + cannot be the culprit for entering the <code + language="java">catch</code> clause. Thus if a <classname + xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/NumberFormatException.html">NumberFormatException</classname> + is being thrown our <code language="java">userInput</code> + variable will already carry a user entered input string. The + compiler however cannot analyze this type of dependency.</para> - <para>Since the possibility of am uninitialized <code + <para>Thus the possibility of an uninitialized <code language="java">userInput</code> variable using just <code - language="java">String userInput;</code> causes a compile time - error <code>Variable 'userInput' might not have been + language="java">String userInput;</code> would cause a compile + time error <code>Variable 'userInput' might not have been initialized</code>.</para> - <para>Thus <code language="java">String userInput = null</code> - would be appropriate as well since the value will actually never - be used.</para> + <para><code language="java">So userInput = null</code> is + sufficient for keeping the compiler happy and inside the catch + clause the variable will definitively carry a<classname> + String</classname> reference.</para> </answer> </qandaentry> </qandadiv> @@ -969,6 +979,25 @@ System.out.println(result);</programlisting> <programlisting language="java">final BigDecimal zero_dot_99 = new BigDecimal("0.99"); final BigDecimal zero_dot_1 = new BigDecimal("0.1"); +BigDecimal + result = zero_dot_99.subtract(zero_dot_1); // Subtracting 0.1 + + result = result.subtract(zero_dot_1); // Subtracting 0.1 + result = result.subtract(zero_dot_1); // Subtracting 0.1 + +System.out.println(result);</programlisting> + + <screen>0.69</screen> + </figure> + + <figure xml:id="sd1_numbers_fig_usingBigDecimalChaining"> + <title>Chaining <classname + xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html">BigDecimal</classname> + operations</title> + + <programlisting language="java">final BigDecimal zero_dot_99 = new BigDecimal("0.99"); +final BigDecimal zero_dot_1 = new BigDecimal("0.1"); + BigDecimal result = zero_dot_99. subtract(zero_dot_1). subtract(zero_dot_1). @@ -979,6 +1008,46 @@ System.out.println(result);</programlisting> <screen>0.69</screen> </figure> + <qandaset defaultlabel="qanda" + xml:id="sd1_workingWithNumbers_BigDecimalChaining"> + <title>Chaining subtract method calls</title> + + <qandadiv> + <qandaentry> + <question> + <para>Explain the chaining mechanism implementing three successive + subtractions in <xref + linkend="sd1_numbers_fig_usingBigDecimalChaining"/>.</para> + </question> + + <answer> + <para>We may re-write the statement in question:</para> + + <programlisting language="none">result = zero_dot_99.subtract(zero_dot_1).subtract(zero_dot_1).subtract(zero_dot_1); + \ / / / + \ / / / + \ / / / + 0.99 - 0.1 / / + \ / / + \ / / + \ / / + 0.98 - 0.1 / + \ / + \ / + 0.97 - 0.1 + == 0.96</programlisting> + + <para>Each <methodname>subtract(...)</methodname> call returns a + new result instance of class <classname + xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html">BigDecimal</classname>. + We can thus chain a subsequent + <methodname>subtract(...)</methodname> call using this returned + instance.</para> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + <figure xml:id="sd1_numbers_fig_usingBigDecimalFeatures"> <title><classname xlink:href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html">BigDecimal</classname> -- GitLab