C 和其他一些早期语言经常会有多中处理异常的方式,这些方式基本都是便宜形式,并且不是语言的一部分。典型的案例就是放回一个特殊的值或者设置一个特殊的 flag,接收方根据这个返回值来进行相应的处理。但是渐渐的码农们突然意识到,自己定义的异常情况可能是不充分的,并且为了覆盖这些没有覆盖到的情况,代码会变得越来越难以维护。
Exercise 1: (2) Create a class with a main( ) that throws an object of class Exception inside a try block. Give the constructor for Exception a String argument. Catch the exception inside a catch clause and print the String argument. Add a finally clause and print a message to prove you were there.
// output // my exception msg... // Into final cluster...
Exercise 2: (1) Define an object reference and initialize it to null. Try to call a method through this reference. Now wrap the code in a try-catch clause to catch the exception.
Exercise 4: (2) Create your own exception class using the extends keyword. Write a constructor for this class that takes a String argument and stores it inside the object with a String reference. Write a method that displays the stored String. Create a try-catch clause to exercise your new exception.
publicclassWhoCalled{ staticvoidf(){ // Generate an exception to fill in the stack trace try { thrownew Exception(); } catch (Exception e) { for (StackTraceElement ste : e.getStackTrace()) System.out.println(ste.getMethodName()); } }
publicclassRethrowing{ publicstaticvoidf()throws Exception { System.out.println("originating the exception in f()"); thrownew Exception("thrown from f()"); }
// originating the exception in f() // Inside g(),e.printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.f(Rethrowing.java:6) // at reading.container.Rethrowing.g(Rethrowing.java:11) // at reading.container.Rethrowing.main(Rethrowing.java:31) // main: printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.f(Rethrowing.java:6) // at reading.container.Rethrowing.g(Rethrowing.java:11) // at reading.container.Rethrowing.main(Rethrowing.java:31) // /--------------------- Dash --------------------/ // originating the exception in f() // Inside h(),e.printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.f(Rethrowing.java:6) // at reading.container.Rethrowing.h(Rethrowing.java:21) // at reading.container.Rethrowing.main(Rethrowing.java:38) // main: printStackTrace() // java.lang.Exception: thrown from f() // at reading.container.Rethrowing.h(Rethrowing.java:25) // at reading.container.Rethrowing.main(Rethrowing.java:38)
publicclassRethrowNew{ publicstaticvoidf()throws OneException { System.out.println("originating the exception in f()"); thrownew OneException("thrown from f()"); }
// originating the exception in f() // Caught in inner try, e.printStackTrace() // reading.container.OneException: thrown from f() // at reading.container.RethrowNew.f(RethrowNew.java:18) // at reading.container.RethrowNew.main(RethrowNew.java:24) // Caught in outer try, e.printStackTrace() // reading.container.TwoException: from inner try // at reading.container.RethrowNew.main(RethrowNew.java:29)
publicDynamicFields(int initialSize){ fields = new Object[initialSize][2]; for (int i = 0; i < initialSize; i++) fields[i] = new Object[]{null, null}; }
public String toString(){ StringBuilder result = new StringBuilder(); for (Object[] obj : fields) { result.append(obj[0]); result.append(": "); result.append(obj[1]); result.append("\n"); } return result.toString(); }
privateinthasField(String id){ for (int i = 0; i < fields.length; i++) if (id.equals(fields[i][0])) return i; return -1; }
privateint getFieldNumber(String id) throws NoSuchFieldException { int fieldNum = hasField(id); if (fieldNum == -1) thrownew NoSuchFieldException(); return fieldNum; }
privateintmakeField(String id){ for (int i = 0; i < fields.length; i++) if (fields[i][0] == null) { fields[i][0] = id; return i; } // No empty fields. Add one: Object[][] tmp = new Object[fields.length + 1][2]; for (int i = 0; i < fields.length; i++) tmp[i] = fields[i]; for (int i = fields.length; i < tmp.length; i++) tmp[i] = new Object[]{null, null}; fields = tmp; // Recursive call with expanded fields: return makeField(id); }
public Object getField(String id)throws NoSuchFieldException { return fields[getFieldNumber(id)][1]; }
public Object setField(String id, Object value) throws DynamicFieldsException { if (value == null) { // Most exceptions don’t have a "cause" constructor. // In these cases you must use initCause(), // available in all Throwable subclasses. DynamicFieldsException dfe = new DynamicFieldsException(); dfe.initCause(new NullPointerException()); throw dfe; } int fieldNumber = hasField(id); if (fieldNumber == -1) fieldNumber = makeField(id); Object result = null; try { result = getField(id); // Get old value } catch (NoSuchFieldException e) { // Use constructor that takes "cause": thrownew RuntimeException(e); } fields[fieldNumber][1] = value; return result; }
publicstaticvoidmain(String[] args){ DynamicFields df = new DynamicFields(3); System.out.println(df); try { df.setField("d", "A value for d"); df.setField("number", 47); df.setField("number2", 48); System.out.println(df); df.setField("d", "A new value for d"); df.setField("number3", 11); System.out.println("df: " + df); System.out.println("df.getField(\"d\") : " + df.getField("d")); Object field = df.setField("d", null); // Exception } catch (NoSuchFieldException e) { e.printStackTrace(System.out); } catch (DynamicFieldsException e) { e.printStackTrace(System.out); } } }
// df: d: A new value for d // number: 47 // number2: 48 // number3: 11
// df.getField("d") : A new value for d // reading.container.DynamicFieldsException // at reading.container.DynamicFields.setField(DynamicFields.java:68) // at reading.container.DynamicFields.main(DynamicFields.java:98) // Caused by: java.lang.NullPointerException // at reading.container.DynamicFields.setField(DynamicFields.java:69) // ... 1 more
// output // Exception in thread "main" java.lang.RuntimeException: From f() // at reading.container.NeverCaught.f(NeverCaught.java:5) // at reading.container.NeverCaught.g(NeverCaught.java:9) // at reading.container.NeverCaught.main(NeverCaught.java:13)
try { // The guarded region: Dangerous activities // that might throw A, B, or C } catch(A a1) { // Handler for situation A } catch(B b1) { // Handler for situation B } catch(C c1) { // Handler for situation C } finally { // Activities that happen every time }
publicclassMultipleReturns{ publicstaticvoidf(int i){ System.out.println("Initialization that requires cleanup"); try { System.out.println("Point 1"); if (i == 1) return; System.out.println("Point 2"); if (i == 2) return; System.out.println("Point 3"); if (i == 3) return; System.out.println("End"); return; } finally { System.out.println("Performing cleanup"); } }
publicstaticvoidmain(String[] args){ for (int i = 1; i <= 4; i++) f(i); } }
// Initialization that requires cleanup // Point 1 // Performing cleanup // Initialization that requires cleanup // Point 1 // Point 2 // Performing cleanup // Initialization that requires cleanup // Point 1 // Point 2 // Point 3 // Performing cleanup // Initialization that requires cleanup // Point 1 // Point 2 // Point 3 // End // Performing cleanup
publicclassStormyInningextendsInningimplementsStorm{ // OK to add new exceptions for constructors, but you // must deal with the base constructor exceptions: publicStormyInning() throws RainedOut, BaseballException { }
// Regular methods must conform to base class: // !public void walk() throws PopFoul {} //Compile error // Interface CANNOT add exceptions to existing // methods from the base class: // !public void event() throws RainedOut {} // If the method doesn’t already exist in the // base class, the exception is OK: publicvoidrainHard()throws RainedOut {}
// You can choose to not throw any exceptions, // even if the base version does: publicvoidevent(){}
// Overridden methods can throw inherited exceptions: publicvoidatBat()throws PopFoul {}
publicstaticvoidmain(String[] args){ try { StormyInning si = new StormyInning(); si.atBat(); } catch (PopFoul e) { System.out.println("Pop foul"); } catch (RainedOut e) { System.out.println("Rained out"); } catch (BaseballException e) { System.out.println("Generic baseball exception"); } // Strike not thrown in derived version. try { // What happens if you upcast? Inning i = new StormyInning(); i.atBat(); // You must catch the exceptions from the // base-class version of the method: } catch (Strike e) { System.out.println("Strike"); } catch (Foul e) { System.out.println("Foul"); } catch (RainedOut e) { System.out.println("Rained out"); } catch (BaseballException e) { System.out.println("Generic baseball exception"); } } }
publicInputFile(String fname)throws Exception { try { in = new BufferedReader(new FileReader(fname)); // Other code that might throw exceptions } catch (FileNotFoundException e) { System.out.println("Could not open " + fname); // Wasn’t open, so don’t close it throw e; } catch (Exception e) { // All other exceptions must close it try { in.close(); } catch (IOException e2) { System.out.println("in.close() unsuccessful"); } throw e; // Rethrow } finally { // Don’t close it here!!! } }
// Section 2: // If construction cannot fail you can group objects: NeedsCleanup nc2 = new NeedsCleanup(); NeedsCleanup nc3 = new NeedsCleanup(); try { // ... } finally { nc3.dispose(); // Reverse order of construction nc2.dispose(); }
publicclassMainException{ // Pass all exceptions to the console: publicstaticvoidmain(String[] args)throws Exception { // Open the file: FileInputStream file = new FileInputStream("MainException.java"); // Use the file ... // Close the file: file.close(); } }