This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Beginning Java and the fly likes Declaring exceptions in interfaces... Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Declaring exceptions in interfaces..." Watch "Declaring exceptions in interfaces..." New topic
Author

Declaring exceptions in interfaces...

Landon Blake
Ranch Hand

Joined: Dec 04, 2003
Posts: 121
I've got an interface that represents objects that you can obtain characters from. I have 2 implementations of this interface. The first one wraps a Java String, and the second one wraps a text file.

The method on the interface used to obtain the character is readCharacter(). I don't need to declare a possible exception for the String implementation, but I would like to for the text file implementaiton. (A lot of things can go wrong when reading data from a file, you know...)

My basic question is this. Do I have to declare that the readCharacter()method throws an exception in my interface if one of the interface implementations might throw an exception?

This doesn't make a whole lot of sense to me, because the designer of an interface might not know anything about possible implementaitons of that interface, but I'm getting some error messages in Eclipse with the above situation, and I can't figure out what else to do besides add the throws clause to the method in the interface.

Thanks for the help.

Landon
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Yes, you have to declare an exception or its superclass in the interface, or implementations won't be allowed to throw it. If you think about it, this must be so; if I've got a variable like this:

YouCharacterGetterInterface ycgi = getOneFromSomewhere();

then all the compiler knows about the methods of ycgi is what it says in the interface. It can't deal with exceptions that aren't declared.

But you shouldn't declare that the methods can throw every single possible exception. You should generally throw a single type, and then implementations have to adapt to that. For example, imagine a declaration like this:

class CharGetterException extends Exception { ... }
...
char getChar() throws CharGetterException;

Then an implementation might look like



[Jess in Action][AskingGoodQuestions]
Carl Trusiak
Sheriff

Joined: Jun 13, 2000
Posts: 3340
Originally posted by Landon Blake:

My basic question is this. Do I have to declare that the readCharacter()method throws an exception in my interface if one of the interface implementations might throw an exception?


Yes, and you actually see this in the Java APIs. Look at StringReader and FileReader both of which implement Readable and the read method throws an IOException.

BTW, it looks like these 2 classes will perform the requirements you have laid out. No need to create them on your own.


I Hope This Helps
Carl Trusiak, SCJP2, SCWCD
Landon Blake
Ranch Hand

Joined: Dec 04, 2003
Posts: 121
Thanks for the responses Carl and Ernest.

This makes it seem like I should always declare every method in all of my interfaces as throwing the generic exception. If I don't, implementers of my interfaces won't get to throw an exception from the implemented methods if they need to.

Is it good coding practice to declare every method in an interface as throwing an exception? If not, how do you choose which methods throw and which do not?

Landon
john cahil
Greenhorn

Joined: Jul 26, 2006
Posts: 12
We do not need to specify each & every exception Instead we are suppose to say base class of all exceptions which are likely to occur , like IOexception
Peter Chase
Ranch Hand

Joined: Oct 30, 2001
Posts: 1970
Originally posted by rahulbhatt @mail.com:
We do not need to specify each & every exception Instead we are suppose to say base class of all exceptions which are likely to occur , like IOexception


Not sure about this. I think you have to take it on a case-by-case basis.

Taking your argument to extremes, all methods would just say they throw Exception. That would clearly not be desirable. (Quite a lot of methods do declare they throw Exception - this is occasionally necessary, but more often just because the developer was too lazy to think what exceptions might really happen).

For each method, you need to think what the caller will want to know about the exceptions that can happen. Will listing lots of individual exceptions make for better or worse code, at the call-site? Will it make the documentation clearer or more muddled?

Sometimes, declaring that a method throws IOException, when really it can perhaps only throw FileNotFoundException, can be bad. This is particularly true if the class/interface being designed is expected to be subclassed. If you declare IOException, then a subclass can throw any IOException, even ones that might not be appropriate to the situation.


Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Originally posted by Landon Blake:

This makes it seem like I should always declare every method in all of my interfaces as throwing the generic exception. If I don't, implementers of my interfaces won't get to throw an exception from the implemented methods if they need to.


Look carefully at my code example. The code in my implementation method throws one kind of exception, but the implementation catches it and re-throws it as the type of exception allowed by the interface. This is a very general and useful pattern.

Is it good practice to declare every method of every interface can throw an exception? Most of the time, probably yes.

For examples of both of these answers, look at the java.sql package (JDBC), which is mostly interfaces. Most methods are declared to throw SQLException; the implementations, which are drivers that communicate over the network, or work with files, etc, are obviously going to hit some IOExceptions. What the implemnentations do is exactly what I showed above: catch them and re-throw as SQLExceptions.
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

rahulbhatt,

Welcome to JavaRanch!

We have a strict policy on display names, which must be a real first and last name with a space between. An email address doesn't qualify as a name! Please go here and fix your display name up, pronto. Thanks, pardner!
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
I strongly recommend against using exceptions. I have long said it, but I have also refused to start the associated rant; but I'll go the next step anyway. There are many more steps after this one, so I urge you to consider this rant in at least some detail

You can use this information (which is basically a paraphrase of some programming language theory that hass long been known) to observe the checked versus unchecked exception debate - which from my perspective - makes it somewhat amusing from the sideline.

I will start with the most trivial code sample:

The formal contract of this type can be roughly paraphrased in English as "return some Y for any given X. For a given X, the same Y will be returned from creation of contract implementation until the collapse of the universe/spacetime (better known as referential transparency)".

A problem comes about; what if there is no associated Y with the given X? The contract currently does not stipulate the required behaviour. Here are some of the conventional approaches:
1) return some dynamically typed placeholder for "nothing" such as null (look at java.util.Map for an example)
2) throw an exception
I will ignore 1) simply because I believe (at least, I hope) it is obvious how defective this approach is. Looking at point 2); the contract now stipulates the behaviour for the given condition of no association. Simply the 'get' method has two return values: one is an exception, and the other is a X. When the client uses this method, there will be two alternative path executions implied by a try/catch block. The try path will execute if the association exists and the catch block will execute if the association does not exist - solved right?

Not according to many - "exceptions should not be used for control flow". This is fallacious, but let's explore it a little. Many would prefer to resort to point 1 as a result of this (religious? faithful? unsubstantiated?) belief. This will result in code that closely resembles the try/catch except that it will instead use if/else - comparing with 'null'. This is considered more acceptable for no apparent reason.

But there is a reason - Sun originally "marketed" exceptions as "exceptional conditions" (and many other things which were derived from previous languages). Therefore, neither "no such association" and "there is an association" might be considered "exceptional conditions" many take option 1). Still, I hope that it is obvious that this is not a solution at all.

The point is, the differences between if/else and try/catch are entirely superificial and a result of many marketing techniques and strategies that have been used over the decades. I have news - marketers lie - but I think we all know that. One could talk about the resulting bytecode of try/catch versus if/else, but why must one consider the VM Specification in order to use a programming language? Better, why can't the runtime compiler optimise it away anyway? It's just a simple conditional branch. There is another point; why is the exception path "no such association" while the other is "association exists, here is the value"? In other words, the "exception" path and the "not exception" path should be considered agnostic from all else except that they are alternative paths of execution. I could rant on with many more points that derive some profound conclusions but I'll stop here and move on.

Java does not have closures. Oh well, what a bummer; not the greatest of defects, but still quite a bummer. You can google about and find out the original reasoning of the language creators, but let's not empathise for too long. Java has "quasi-closures" or "callbacks" or "whatever you want to call it but it's not a real closure". There are reasons why and I'm sure investigative skills would quickly yield those reasons, but in any case, I'll call it a quasi-closure from here on. Here is an example:

Yep this "quasi-closure" has been around for a long time. The java.lang.Thread class "calls back on it" in order to determine what to execute in the thread. We've known that for a long time - but perhaps we've never viewed it as a quasi-closure or simply "a block of code that is passed for execution". In fact, it is the closest to a "quasi-closure" as you'll get - assuming you ignore the common, but ill-perceived, association with java.lang.Thread - the relationship from java.lang.Thread to java.lang.Runnable is unidirectional.

To be completely agnostic from java.lang.Runnable - even considering the common misconception - let's rewrite the contract:

There we go - can't say that has anything to do with threads now! (mumble under your breath "neither does java.lang.Runnable" - imagine how poor Galileo felt). Anyway, let's tie this to the exception problem. Consider the following:

If the association does not exist, we will "call back" on the quasi-closure, otherwise, we will return the associated value. There we go, solved! Not so fast - an attempt to implement this will quickly highlight the fact that you
have no "definite point of return". Ever seen the compile-time error "missing return statement"?

We can solve this problem - but we must abandon the "imperative" part of "imperative programming":

This solves the problem - no need to ever use exceptions again. But, unfortunately, there are problems.
1) Since Java has no real closures, it is impossible to write an API that has a dependency on some "imperative" API. One solution to this is to write a subtype of each quasi-closure that is "imperative". Example:

This is quite ugly (hopefully obvious) and is somewhat oxymoronic, but one must concede at this point - the language is quite broken.
2) The code will quickly become extremely verbose - again I hope this is obvious.

Code quickly becomes "functional", loops may be replaced with recursion and all those nice things that have been around for a while - but at a cost. One must consider this cost before using this approach. I certainly don't condone using it for all cases in Java - since the language simply doesn't support it well. Alternatively, one could abandon Java altogether and use a better language, but then we'd be leaving the context of this forum

Certainly, I favour the above approach over the use of exceptions for all cases. I better go do something more useful than ranting. Enjoy and always remember to Think for Yourself


Tony Morris
Java Q&A (FAQ, Trivia)
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
Sorry, just realised this was the beginner's forum. Perhaps it belongs in one of the others anyway, since the "exception on an interface" issue is non-trivial.
Ricky Clarkson
Ranch Hand

Joined: Jul 27, 2006
Posts: 131
The end result using Tony Morris' mechanism isn't too bad, if we borrow the idea of the Maybe type from Haskell. A Maybe can 'be' a T or it can 'be' a Nothing. I will omit the Nothing from the Java equivalent, and rather than be a T, it will contain a T (or rather a reference to a T).



Then to use this, you would have:



If getUser or getAddress failed, then 'maybe' would contain nothing. Otherwise, it would contain Fred's address. Of course, this isn't enough for error reporting, in which case Haskell's Either type would be useful to emulate in Java.

Here's what getUser might look like. We'll imagine an imperativeGetUser for now, that returns a String or null, that getUser calls. We'll also imagine an imperativeGetAddress in User, that getAddress calls. This could be improved upon to remove the need for these imperativeCalls, maybe I'll do that later.



Var<T> looks like:



If this all looks strange to you, it did to me too. I spent some time yesterday getting to grips with the ideas of monads. Unfortunately most explanations seem to involve Haskell syntax, which presented an extra barrier for me, but I think this is an interesting way of avoiding exceptions.

Exceptions are worth avoiding in Java, because they are not normally in exceptional conditions, but impose a hefty performance penalty when they occur.

For example, an IOException isn't that unusual. A NumberFormatException isn't either.

Note that you can turn off stack traces in the VM options (ask me how if you want to know, I'll look it up again).

[ July 27, 2006: Message edited by: Ricky Clarkson ]
[ July 27, 2006: Message edited by: Ricky Clarkson ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Declaring exceptions in interfaces...
 
Similar Threads
Content is not allowed in prolog (EDIT: emergency code fix help!)
deadly diamond of death syndrome :)
Exceptions
How to return a value with a method that throws an exception...
RecordNotFoundException in locking