[ Pobierz całość w formacie PDF ]
.By forcing the derived-class methods to conform to theexception specifications of the base-class methods, substitutability of objectsis maintained.[ Add Comment ]The overridden event( )method shows that a derived-class version of a method may choose not to throwany exceptions, even if the base-class version does.Again, this is fine sinceit doesn’t break any code that is written—assuming the base-classversion throws exceptions.Similar logic applies to atBat( ), whichthrows PopFoul, an exception that is derived from Foul thrown bythe base-class version of atBat( ).This way, if someone writes codethat works with Inning and calls atBat( ), they must catchthe Foul exception.Since PopFoul is derived from Foul, theexception handler will also catch PopFoul.[ Add Comment ]The last point of interest is inmain( ).Here you can see that if you’re dealing with exactlya StormyInning object, the compiler forces you to catch only theexceptions that are specific to that class, but if you upcast to the base typethen the compiler (correctly) forces you to catch the exceptions for the basetype.All these constraints produce much more robust exception-handlingcode[55].[ Add Comment ]It’s useful to realize thatalthough exception specifications are enforced by the compiler duringinheritance, the exception specifications are not part of the type of a method,which is comprised of only the method name and argument types.Therefore, youcannot overload methods based on exception specifications.In addition, justbecause an exception specification exists in a base-class version of a methoddoesn’t mean that it must exist in the derived-class version of themethod.This is quite different from inheritance rules, where a method in thebase class must also exist in the derived class.Put another way, the“exception specification interface” for a particular method maynarrow during inheritance and overriding, but it may not widen—this isprecisely the opposite of the rule for the class interface during inheritance.[ Add Comment ]ConstructorsWhen writing code with exceptions,it’s particularly important that you always ask, “If an exceptionoccurs, will this be properly cleaned up?” Most of the time you’refairly safe, but in constructors there’s a problem.The constructor putsthe object into a safe starting state, but it might perform someoperation—such as opening a file—that doesn’t get cleaned upuntil the user is finished with the object and calls a special cleanup method.If you throw an exception from inside a constructor, these cleanup behaviorsmight not occur properly.This means that you must be especially diligent whileyou write your constructor.[ Add Comment ]Since you’ve just learned aboutfinally, you might thinkthat it is the correct solution.But it’s not quite that simple, becausefinally performs the cleanup code every time, even in thesituations in which you don’t want the cleanup code executed until thecleanup method runs.Thus, if you do perform cleanup in finally, you mustset some kind of flag when the constructor finishes normally so that youdon’t do anything in the finally block if the flag is set.Becausethis isn’t particularly elegant (you are coupling your code from one placeto another), it’s best if you try to avoid performing this kind of cleanupin finally unless you are forced to.[ Add Comment ]In the following example, a class calledInputFile is created that opens a file and allows you to read it one line(converted into a String) at a time.It uses the classesFileReader andBufferedReader from theJava standard I/O library that will be discussed in Chapter 11, but which aresimple enough that you probably won’t have any trouble understanding theirbasic use://: c10:Cleanup.java// Paying attention to exceptions// in constructors.import java.io.*;class InputFile {private BufferedReader in;InputFile(String fname) throws Exception {try {in =new BufferedReader(new FileReader(fname));// Other code that might throw exceptions} catch(FileNotFoundException e) {System.err.println("Could not open " + fname);// Wasn't open, so don't close itthrow e;} catch(Exception e) {// All other exceptions must close ittry {in.close();} catch(IOException e2) {System.err.println("in.close() unsuccessful");}throw e; // Rethrow} finally {// Don't close it here!!!}}String getLine() {String s;try {s = in.readLine();} catch(IOException e) {System.err
[ Pobierz całość w formacie PDF ]