001package beginner; 002 003import com.sandwich.koan.Koan; 004 005import java.io.IOException; 006 007import static com.sandwich.koan.constant.KoanConstants.__; 008import static com.sandwich.util.Assert.assertEquals; 009 010public class AboutExceptions { 011 012 private void doStuff() throws IOException { 013 throw new IOException(); 014 } 015 016 @Koan 017 public void catchCheckedExceptions() { 018 String s; 019 try { 020 doStuff(); 021 s = "code ran normally"; 022 } catch (IOException e) { 023 s = "exception thrown"; 024 } 025 assertEquals(s, __); 026 } 027 028 @Koan 029 public void useFinally() { 030 String s = ""; 031 try { 032 doStuff(); 033 s += "code ran normally"; 034 } catch (IOException e) { 035 s += "exception thrown"; 036 } finally { 037 s += " and finally ran as well"; 038 } 039 assertEquals(s, __); 040 } 041 042 @Koan 043 public void finallyWithoutCatch() { 044 String s = ""; 045 try { 046 s = "code ran normally"; 047 } finally { 048 s += " and finally ran as well"; 049 } 050 assertEquals(s, __); 051 } 052 053 private void tryCatchFinallyWithVoidReturn(StringBuilder whatHappened) { 054 try { 055 whatHappened.append("did something dangerous"); 056 doStuff(); 057 } catch (IOException e) { 058 whatHappened.append("; the catch block executed"); 059 return; 060 } finally { 061 whatHappened.append(", but so did the finally!"); 062 } 063 } 064 065 @Koan 066 public void finallyIsAlwaysRan() { 067 StringBuilder whatHappened = new StringBuilder(); 068 tryCatchFinallyWithVoidReturn(whatHappened); 069 assertEquals(whatHappened.toString(), __); 070 } 071 072 @SuppressWarnings("finally") 073 // this is suppressed because returning in finally block is obviously a compiler warning 074 private String returnStatementsEverywhere(StringBuilder whatHappened) { 075 try { 076 whatHappened.append("try"); 077 doStuff(); 078 return "from try"; 079 } catch (IOException e) { 080 whatHappened.append(", catch"); 081 return "from catch"; 082 } finally { 083 whatHappened.append(", finally"); 084 // Think about how bad an idea it is to put a return statement in the finally block 085 // DO NOT DO THIS! 086 return "from finally"; 087 } 088 } 089 090 @Koan 091 public void returnInFinallyBlock() { 092 StringBuilder whatHappened = new StringBuilder(); 093 // Which value will be returned here? 094 assertEquals(returnStatementsEverywhere(whatHappened), __); 095 assertEquals(whatHappened.toString(), __); 096 } 097 098 private void doUncheckedStuff() { 099 throw new RuntimeException(); 100 } 101 102 @Koan 103 public void catchUncheckedExceptions() { 104 // What do you need to do to catch the unchecked exception? 105 doUncheckedStuff(); 106 } 107 108 @SuppressWarnings("serial") 109 static class ParentException extends Exception { 110 } 111 112 @SuppressWarnings("serial") 113 static class ChildException extends ParentException { 114 } 115 116 private void throwIt() throws ParentException { 117 throw new ChildException(); 118 } 119 120 @Koan 121 public void catchOrder() { 122 String s = ""; 123 try { 124 throwIt(); 125 } catch (ChildException e) { 126 s = "ChildException"; 127 } catch (ParentException e) { 128 s = "ParentException"; 129 } 130 assertEquals(s, __); 131 } 132 133 @Koan 134 public void failArgumentValidationWithAnIllegalArgumentException() { 135 // This koan demonstrates the use of exceptions in argument validation 136 String s = ""; 137 try { 138 s += validateUsingIllegalArgumentException(null); 139 } catch (IllegalArgumentException ex) { 140 s = "caught an IllegalArgumentException"; 141 } 142 assertEquals(s, __); 143 } 144 145 @Koan 146 public void passArgumentValidationWithAnIllegalArgumentException() { 147 // This koan demonstrates the use of exceptions in argument validation 148 String s = ""; 149 try { 150 s += validateUsingIllegalArgumentException("valid"); 151 } catch (IllegalArgumentException ex) { 152 s = "caught an IllegalArgumentException"; 153 } 154 assertEquals(s, __); 155 } 156 157 private int validateUsingIllegalArgumentException(String str) { 158 // This is effective and both the evaluation and the error message 159 // can be tailored which can be particularly handy if you're guarding 160 // against more than null values 161 if (null == str) { 162 throw new IllegalArgumentException("str should not be null"); 163 } 164 return str.length(); 165 } 166}