You missed the correct solution in your logging
example.  Obviously, various implementations will
throw different sets of exceptions so the right way to
handle it is to create a checked LoggingException and
throw that from the log methods.  The implementations
will wrap their exceptions in LoggingExceptions.  This
keeps all of the advantages of checked exception
handling without resorting to throwing/catching
Exception.

RuntimeExceptions indicate programmer error.  In rare
cases they are thrown when you must bypass several
application layers (see SecurityException for an
example).

David

--- Rodney Waldhoff <[EMAIL PROTECTED]> wrote:
> I'm not sure that "ownership" necessarily enters
> into it, but here's some
> concrete examples:
> 
> Consider a simple logging API:
> 
> interface Log {
>   void debug(String message);
>   void info(String message);
>   void fatal(String message);
> }
> 
> One implementation of that interface might write the
> output to standard
> out.  Since System.out (java.io.PrintStream I guess)
> never throws a
> checked exception, there's no need to ever throw a
> checked exception from
> that implementation or that interface.
> 
> Another implementation of that interface might write
> to some external
> file.  Any of those write calls might throw an
> IOException, in which case
> I should add "throws IOException" to all of my
> logging methods unless I'm
> gonna swallow all of those exceptions (while
> swallowing exceptions *might*
> be OK in the logging case, it certainly isn't OK in
> the general case).
> 
> interface Log {
>   void debug(String message) throws IOException;
>   void info(String message) throws IOException;
>   void fatal(String message) throws IOException;
> }
> 
> Now even if I'm using a System.out logger, I've got
> to catch or throw
> IOException, just in case.
> 
> Yet another implementation of that interface might
> write log messages to a
> database.  Any of those insert statements might
> throw a SQLException, in
> which case I should add "throws SQLException" to all
> my logging methods:
> 
> interface Log {
>   void debug(String message) throws IOException,
> SQLException;
>   void info(String message) throws IOException,
> SQLException;
>   void fatal(String message) throws IOException,
> SQLException;
> }
> 
> Of course, I'll never be able to anticipate all of
> the specific types of
> Exception that might be thrown.  I may as well drop
> back to the general
> case:
> 
> interface Log {
>   void debug(String message) throws Exception;
>   void info(String message) throws Exception;
>   void fatal(String message) throws Exception;
> }
> 
> but now I have all of the disadvantages of checked
> exceptions--I need to
> explictly catch or throw Exception every time I
> invoke one of these
> methods--but none of the advantages of checked
> exceptions--I don't have
> any guarentee that the specific type of exception
> that might be throw by
> the implementation code is going to be specifically
> handled by the calling
> code.  How's this any better than RuntimeException?
> 
> As another example, consider java.util.Iterator.  I
> can do lots of useful
> things with Iterators (chain them, filter them,
> transform them, apply some
> function to each element within the iteration,
> etc.).  One source of
> Iterators is the Collections API.  But it's not
> difficult to create an
> Iterator from other sources--say an Iterator over
> the lines in a file:
> 
> class LineIterator implements Iterator {
>   LineIterator(BufferedReader reader) {
>      this.reader = reader;
>   }
> 
>   Object next() {
>     if(hasNext()) {
>        nextSet = false;
>        return nextLine;
>     } else {
>        throw new NoSuchElementException();
>     }
>   }
> 
>   boolean hasNext() {
>     if(!nextSet) {
>       setNext();
>     }
>     return nextLine != null;
>   }
> 
>   private setNext() throws IOException {
>      nextLine = reader.readLine();
>      nextSet = true;
>   }
> 
>   private Reader reader;
>   private String nextLine;
>   private boolean nextSet = false;
> }
> 
> or the values in some column in a database table:
> 
> class ColumnIterator implements Iterator {
>   ColumnIterator(ResultSet rset, int column) {
>      this.rset = rset;
>      this.column = column;
>   }
> 
>   Object next() {
>     if(hasNext()) {
>        nextSet = false;
>        return next;
>     } else {
>        throw new NoSuchElementException();
>     }
>   }
> 
>   boolean hasNext() {
>     if(!nextSet) {
>       setNext();
>     }
>     return nextSet;
>   }
> 
>   private setNext() throws SQLException {
>      if(rset.next()) {
>         next = rset.getString(column);
>         nextSet = true;
>      } else {
>         nextSet = false;
>      }
>   }
> 
>   private ResultSet rset;
>   private int column;
>   private Object next;
>   private boolean nextSet = false;
> }
> 
> Of course, those don't quite work because the
> checked IOExceptions and
> SQLExceptions aren't being handled.  In theory, one
> could add "throws
> Exception" to all of the Iterator methods (subject
> to the limitations
> above), but in practice that's not going to happen.
> 
> Why not just throw RuntimeException in this case
> (and ignore the tunneling
> concept)?  Because there are times when I might be
> able to handle or
> announce the underlying cause:
> 
> // process the commands in the given stream,
> ignoring lines that start
> with #
> void processCommandStream(Reader in) throws
> IOException {
>    UnaryPredicate startsWithHash = new
> UnaryPredicate() {
>       public boolean evaluate(Object obj) {
>          return ((String)obj).startsWith("#");
>       }
>    }
> 
>    Iterator iterator = new FilteringIterator(
>       new NotPredicate(startsWithHash),
>       new LineIterator(in));
> 
>    try {
>      while(iterator.hasNext()) {
>         processCommand((String)iterator.next());
>      }
>    } catch(TunneledException e) {
>      if(e.getException() instanceof IOException) {
>         throw (IOException)(e.getException());
>      }
>    }
> 
=== message truncated ===


__________________________________
Do you Yahoo!?
SBC Yahoo! DSL - Now only $29.95 per month!
http://sbc.yahoo.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to