Discussion:
Why does Java require the throws clause? Good or bad language design?
(too old to reply)
James Harris
2007-02-07 08:11:03 UTC
Permalink
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer to
declare what a method /may/ throw?

To quote one: "If you write a method that throws an exception, then
the Java compiler wil require that you do one of two things: you must
either declare that the method throws the exception using the 'throws'
keyword, or else you must provide a catch exception handler to catch
that exception." - Java Programming Explorer.

Is there really value in Java's behaviour? Or is this an unnecessary
burden on the programmer? Why not simply accept exceptions can be
thrown which are not listed, and deal with them in the innermost catch
clause which matches?

Conversely, if there is a chain of methods: aa calls bb calls cc calls
dd, and dd declares that it throws FileNotFoundException, if we don't
want to handle it in cc do we need to declare that it also throws
FileNotFoundException... and so on through callers to cc etc?

In terms of code maintenance, if dd could once throw a given exception
but now, because the relevant code has been removed, it cannot does cc
still need to provide for handling the exception simply /because/ it
is listed in dd's throws clause?

Any replies appreciated and please keep comp.lang.misc in the
crosspost list as it's relevant to language design principles. Thanks.
Alex Hunsley
2007-02-07 10:12:07 UTC
Permalink
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer to
declare what a method /may/ throw?
To quote one: "If you write a method that throws an exception, then
the Java compiler wil require that you do one of two things: you must
either declare that the method throws the exception using the 'throws'
keyword, or else you must provide a catch exception handler to catch
that exception." - Java Programming Explorer.
The theory is that by mkaing the programmer explicitly acknowledge what
(checked) exceptions may be thrown, they will deal with them appropriately.
Of course, it is possible to write:

catch (Exception e) {
// nothing
}

But then of course the 'blame' lies squarely on the programmer.
Post by James Harris
Is there really value in Java's behaviour?
Yes.
Post by James Harris
Or is this an unnecessary
burden on the programmer?
There is some burden - obviously declaring "throws" on lots of methods
can be annoying - but you can use strategies like wrapped exceptions (of
which I posted in comp.lang.java.programmer in the last few days).
Post by James Harris
Why not simply accept exceptions can be
thrown which are not listed,
The theory is that the lack of explicitness would a bad thing. And if
you think about it, whether or not a method throws a certain type of
exception *is* in effect part of that method's interface.
Post by James Harris
and deal with them in the innermost catch
clause which matches?
Doesn't make much sense. Lower down code doesn't always know exactly how
to handle the exceptional circumstance, and so you'd end up signalling
to higher levels that something bad happened - so exceptions handle that
(at some cost, e.g. setup time, but for exceptional circumstances, that
isn't so bad).
Post by James Harris
Conversely, if there is a chain of methods: aa calls bb calls cc calls
dd, and dd declares that it throws FileNotFoundException, if we don't
want to handle it in cc do we need to declare that it also throws
FileNotFoundException... and so on through callers to cc etc?
Yup. Or use a wrapped exception to wrap all possible exceptions, hence
protecting your interfaces from mucho changes everytime some deep code
throws a new sort of exception (or *stops* throwing some sort).
Post by James Harris
In terms of code maintenance, if dd could once throw a given exception
but now, because the relevant code has been removed, it cannot does cc
still need to provide for handling the exception simply /because/ it
is listed in dd's throws clause?
Java complains (compile error) if you declare a method as throwing a
checked exception when in fact it doesn't. So your above situation can't
happen - it won't compile.

lex
Lew
2007-02-07 13:18:08 UTC
Permalink
Post by Alex Hunsley
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer to
declare what a method /may/ throw?
The theory is that by mkaing the programmer explicitly acknowledge what
(checked) exceptions may be thrown, they will deal with them appropriately.
catch (Exception e) {
// nothing
}
But then of course the 'blame' lies squarely on the programmer.
Post by James Harris
Is there really value in Java's behaviour?
Yes.
Post by James Harris
Or is this an unnecessary burden on the programmer?
Why not simply accept exceptions can be
thrown which are not listed,
The theory is that the lack of explicitness would a bad thing. And if
you think about it, whether or not a method throws a certain type of
exception *is* in effect part of that method's interface.
There are always unchecked exceptions. But Alex is right, in many cases you
need or want to make the exception part of a method's interface, and declaring
it so is no different than declaring that a method, say, takes a String arg.
Does declaring method parameters place an "undue" burden on a programmer?

If you as a programmer really don't see the value of declaring exceptions,
don't throw them, or rely entirely on unchecked exceptions. After a while you
will discover scenarios where dealing with the results thereby is actually
harder than dealing with checked exceptions.

One of the major flaws, perhaps the major flaw with much production code is
that the programmers did not account for all possible exceptional
circumstances. Such programs fubar on their users all the time. You have to
take the care as a programmer to deal with things like unexpected inputs, lost
connections and the myriad of unhappy events that can befall a program.

With or without exceptions.

There is no responsible way to avoid this aspect of programming.

The burden isn't in the declaration of exceptions. Au contraire, exceptions
help you reduce the burden of dealing with all the corner cases.

- Lew
Robbert Haarman
2007-02-07 22:15:45 UTC
Permalink
Post by Lew
There are always unchecked exceptions. But Alex is right, in many cases you
need or want to make the exception part of a method's interface, and
declaring it so is no different than declaring that a method, say, takes a
String arg. Does declaring method parameters place an "undue" burden on a
programmer?
That's another good question. My answer would be that it depends on what
you are doing. If your method only deals with parameters of one type, or
if it should accept values of any type that is compatible with what the
method does (e.g. the other methods it calls), then, yes, I would call
mandatory signature declarations an unnecessary burden. If, on the other
hand, you want to specialize methods on the types of their arguments
(polymorphism), then specifying those types is, obviously, necessary.
Post by Lew
If you as a programmer really don't see the value of declaring exceptions,
don't throw them, or rely entirely on unchecked exceptions. After a while
you will discover scenarios where dealing with the results thereby is
actually harder than dealing with checked exceptions.
I don't believe so. Just because you do not explicitly list the
exceptions a method can throw does not mean that this information is not
available. You can always use (static) analysis to determine which
exceptions a method could throw.

You can always implement your own system to enforce that certain
exceptions are caught or otherwise handled if this proves beneficial in
your case. It does not have to be hard-coded in the language, forcing
the burden on situations where the benefits are not as great.
Post by Lew
The burden isn't in the declaration of exceptions. Au contraire, exceptions
help you reduce the burden of dealing with all the corner cases.
I agree with the second part, but I don't agree that Java's take on
exceptions is not a burden. Often, the right thing to do with an
exception is to propagate it up the call stack. Often, the right
response to an error is to abort the process with an error message. In
many languages, these are the default behaviors, and you get them for
free.

In Java, you are required to write an exception handler if you want a
checked exception to abort the program with an error message. You also
have to add checked exceptions to throws clauses if you do not want to
handle them locally, but want them to propagate up the call stack. These
are arguably unnecessary efforts that have to be made not once, but
after certain refactorings, as well.

The rationale for Java's explicitness and mandatory declarations is that
they make programs more robust. They have that potential, but the extra
burden they impose on programmers also means there is less time to
perform other actions that make programs more robust. Also, it is not
uncommon for programmers to specify Object as an argument type or
Exception as an exception type, avoiding some of the burden Java imposes
on them, but simultaneously throwing away the benefits of the system.
Still, it demonstrates that, sometimes, Java's way of doing things is
percieved as less than desirable.

To conclude, my stance on the issue is that since (1) Java's explicit
approach is not almays desirable and (2) the benefits of Java's approach
can be obtained without mandating declarations in all circumstances and
hardcoding checked exceptions into the language, Java does impose an
unnecessary burden on programmers, and there are better approaches than
those Java takes.

Regards,

Bob
--
No cookies found.
Bent C Dalager
2007-02-08 10:44:18 UTC
Permalink
Post by Lew
There are always unchecked exceptions. But Alex is right, in many cases you
need or want to make the exception part of a method's interface, and declaring
it so is no different than declaring that a method, say, takes a String arg.
Does declaring method parameters place an "undue" burden on a programmer?
Well, you could always just write
public void foo(Object... args)
to get rid of that particular burden :-)

And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .

Cheers
Bent D
--
Bent Dalager - ***@pvv.org - http://www.pvv.org/~bcd
powered by emacs
Robbert Haarman
2007-02-08 11:13:22 UTC
Permalink
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
It is true that this removes the effort of changing the declaratiens in
response to refactoring, but Java will still impose burdens on the
programmer. First, they have to actually type "Object" before every
argument and "throws Throwable" after every method declaration.
Secondly, if you actually want to use these arguments and throwables,
you will have to downcast them to another class, because Object and
Throwable probably don't have the methods and fields you need. This
requires more typing. It also incurs a performance penalty, because the
casts will be checked at run time. In the end, you get the worst of
dynamic typing and the worst of mandatory declarations, all in one
program.

Regards,

Bob
--
That that is is that that is not not, that is, not that that is not.
Lew
2007-02-08 12:52:40 UTC
Permalink
Post by Robbert Haarman
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
In the end, you get the worst of
dynamic typing and the worst of mandatory declarations, all in one
program.
Which is why newsgroup readers have to watch out for humorous replies, and not
try actually to implement them.

- Lew
Robbert Haarman
2007-02-08 13:48:27 UTC
Permalink
Post by Lew
Post by Robbert Haarman
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
In the end, you get the worst of
dynamic typing and the worst of mandatory declarations, all in one
program.
Which is why newsgroup readers have to watch out for humorous replies, and
not try actually to implement them.
Point taken.

On the other hand, people do actually write code like that. Well.
perhaps not "throws Throwable", but certainly "throws Exception". And
anyone who has been programming in Java for some time will have seen the
likes of

void add(Object o) ...

and

((SomeClass) someContainer.get(someKey)).someMethod(...)

It's not just misguided programmers that write such code; Java was full
of it before the type system overhaul.

Regards,

Bob
--
Two wrongs do not make one right, but three lefts do.
nukleus
2007-02-08 15:20:17 UTC
Permalink
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
In the end, you get the worst of
dynamic typing and the worst of mandatory declarations, all in one
program.
Which is why newsgroup readers have to watch out for humorous replies, and
not try actually to implement them.
Point taken.
On the other hand, people do actually write code like that. Well.
perhaps not "throws Throwable", but certainly "throws Exception".
Not much different from throws Throwable
as you loose any and all the precision.
Basically, your program is screwed beyond repair
and the entire exceptions mechanism needs to be redesigned.
Post by Robbert Haarman
And
anyone who has been programming in Java for some time will have seen the
likes of
void add(Object o) ...
and
((SomeClass) someContainer.get(someKey)).someMethod(...)
It's not just misguided programmers that write such code; Java was full
of it before the type system overhaul.
Regards,
Bob
nukleus
2007-02-08 15:20:15 UTC
Permalink
Post by Lew
Post by Robbert Haarman
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
In the end, you get the worst of
dynamic typing and the worst of mandatory declarations, all in one
program.
Which is why newsgroup readers have to watch out for humorous replies, and not
try actually to implement them.
I agree with both hands.
These jokers are nothing more than noise makers,
having nothing to contribute of just about ANY value
beyond their "smart ass" image.

And on a technical group, it isn't even laughable.
Post by Lew
- Lew
nukleus
2007-02-08 15:20:14 UTC
Permalink
Post by Robbert Haarman
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
It is true that this removes the effort of changing the declaratiens in
response to refactoring, but Java will still impose burdens on the
programmer. First, they have to actually type "Object" before every
argument and "throws Throwable" after every method declaration.
throws Throwable means your very design is incorrect
as you are entirely missing the granularity of your errors.
You'll never be able to successfuly recover
and forget about reattempting the operation
on a fine grained level as you will be thrown
several layers up.
Post by Robbert Haarman
Secondly, if you actually want to use these arguments and throwables,
you will have to downcast them to another class, because Object and
Throwable probably don't have the methods and fields you need. This
requires more typing. It also incurs a performance penalty, because the
casts will be checked at run time. In the end, you get the worst of
dynamic typing and the worst of mandatory declarations, all in one
program.
A BASIC rule in object oriented programming:

DO NOT USE CASTS.
Unless it is absolutely unavoidable.
Post by Robbert Haarman
Regards,
Bob
nukleus
2007-02-08 15:20:12 UTC
Permalink
Post by Bent C Dalager
Post by Lew
There are always unchecked exceptions. But Alex is right, in many cases you
need or want to make the exception part of a method's interface, and declaring
it so is no different than declaring that a method, say, takes a String arg.
Does declaring method parameters place an "undue" burden on a programmer?
I agree with this position with both hands.

Exceptions can simplify the code but they have to be
fine grained and handles properly at each level.
By declaring that some method throws exception,
you force the upper layers of your code to handle
that exception, and you can, if you wish, handle
the same exception in that same method to display
some error message of final granularity, and then
rethrow that same exception to the higher level
to see if some operation can be retried or do all
the other things they do on the higher level.

Once i started introducing the exception mechanism
in some of old java code, i was unable to compile
the app for days, because of compiler errors
"exception is not handled".
But the more i worked on it, the better the end
results were.

Right now, the program handles just about any
error condition imaginable and displays/logs
the error messages of the most precise description,
plus, on the top of it, it can retry just about
any error condition imaginable, upto simply
turning the power switch off or unplugging your
network cable. As soon, as you plug it back in,
the program will try to redo the LAST operation
it was doing, without restarting the whole cycle
from the top.

Throws clause is probably one of the better benefits
of the entire exception mechanism. Yes, it forces you
to hancle those exceptions on the higher level,
but it all happens during the compile time, preventing
all sorts of error conditions imaginable in the run time.

The only thing i suggest in terms of using exceptions
mechanism in general, is to use fine enough granularity
exceptions and handle them on the most appropriate level.
This way, you have about the most powerful structure,
allowing you to display the error messages of the most
precistion and, at the same tim, try to recover just
about any operation imaginable.

The extreme case: use the exceptions everywhere,
is simply foolish. First of all, you need to understand
the very nature of exceptions and it is essentially
an equivalent of a goto statement, that totally screws
up your stack and throws your program into place
you could not have imagine.

Any program is a fine mix of conditional code
and exceptions. Yes, purely conditional code approach
is way too messy as just after about any call,
you'd have to check on results of it. Otherwise,
you can not be certain that you can proceed,
which ends up in large amounts of unnecessary code
compared to properly used exceptions.

But...

You can't just get away from conditional code,
because it is the VERY NATURE of a program,
which is logic, and logic, its turn, is a conglomeration
of ifs and buts.

If you don't have those ifs and buts,
you'll end up with the most rigid and inflexible,
totalitarian system, forcing users to do things
he could not have imagine in his wildest dreams
he has to EVER do, going to the point of obscene
by requiring you to reboot your box in some extreme
instances.

Just because those masters of delusion
do not think that using fine grained ifs and buts
you'll achieve the most flexible and most pleasant
and comfortable environment for the USER,
which is what your entire app is there for on the
first place.
Post by Bent C Dalager
Well, you could always just write
public void foo(Object... args)
to get rid of that particular burden :-)
Is it supposed to be a joke?
Post by Bent C Dalager
And, of course,
public void foo(Object... args) throws Throwable
may be just the silver bullet we are looking for . . .
Just about the most foolish thing to do.
Once you make the declaration of this type,
you loose ALL the granularity of error condition
handling, and will NEVER be able to recover from
errors and attempt to redo only starting from
the error state in your program and continue on
after error condition has been removed,
which is what just about all real life apps do.

I have over a dozen of custom exceptions
derived at the most fine grained level of
standard exceptions, and handle all the exceptions
starting from the most fine grained
and going upto Exception level itself,
which means that you basically have a fatal error.
It means you have an error condition that was not
handled by ANY of your mechanism. It could be just
about the most innocent operation such as division
by 0, which could be properly handled and the
default values substituted for the error values
and the program could keep crunching along.

Summary:
You create a number of custom exceptions with fine
enough granularity to report/handle just about
ANY error condition imaginable, even in your wildest
dreams, and giving you the most precise scope of
error condition that could be handle locally
to provide the most precise and detailed error
messages or attempt to recover.

You HANDLE those exceptions starting from the most
fine grained level. You may have several levels
of catch blocks and act upon different exceptions
differently. In some cases, the operation could
be recovered by simply restarting the local level
of it. In other cases, the result could be more
brutal, in cases where you lost connection to the net,
or things like that, in which case you'd have to
retry going from higher levels,
and in some cases, those errors could be equivalent
to fatal, in which case you have to decide to either
stop the program completely, close some frames,
or restart it from the top.

"THATs the way you do it".

Good luck.
Post by Bent C Dalager
Cheers
Bent D
Robbert Haarman
2007-02-08 17:06:53 UTC
Permalink
On Thu, Feb 08, 2007 at 03:20:12PM +0000, nukleus wrote:

<insightful comments about using exceptions>

You're right. Exceptions in general, and checked exceptions in
particular, can be very useful and very elegant. I don't think anybody
here doubts that (if so, please post).

However, James's original question was about the trows clause, and the
fact that you have to explicitly list the checked exceptions that a
method throws. In other words, it's not about the utility of exceptions
in general, but about the utility vs. burden of the throws clause.

I particularly dislike the trows clause, and the fact that you have to
add and update throms clauses on all methods that call a certain method,
when these methods are not interested in handling an exceptions
throwable by a "lower" method. However, I am curious what other people,
particularly people who actually _like_ Java, think about the issue.
Post by nukleus
The extreme case: use the exceptions everywhere,
is simply foolish. First of all, you need to understand
the very nature of exceptions and it is essentially
an equivalent of a goto statement, that totally screws
up your stack and throws your program into place
you could not have imagine.
That's not necessarily true. If I understand correctly, in Java there is
indeed no way to get back to the place an exception was thrown from.
However, it doesn't have to be that way. Common Lisp, for example,
allows the operation that caused the error to be retried (e.g. after
changing some parameters) or to specify a return value to be used
instead of the expression that caused the error, in addition to simply
aborting the operation and transfering control to wherever the exception
handler is.

Regards,

Bob
--
Do not meddle in the affairs of sysadmins, for they are quick to anger and
have no need for subtlety.
buggy
2007-02-09 23:32:04 UTC
Permalink
Post by Robbert Haarman
<insightful comments about using exceptions>
+1
Post by Robbert Haarman
However, James's original question was about the trows clause, and the
fact that you have to explicitly list the checked exceptions that a
method throws. In other words, it's not about the utility of exceptions
in general, but about the utility vs. burden of the throws clause.
I particularly dislike the trows clause, and the fact that you have to
add and update throms clauses on all methods that call a certain method,
when these methods are not interested in handling an exceptions
throwable by a "lower" method. However, I am curious what other people,
particularly people who actually _like_ Java, think about the issue.
I like the throws clause. Yes when you add a new exception deep within a
call stack, you must then add a throws clause up the chain.

This is a good thing.

By forcing you to add throws clauses, the language forces YOU to
determine where the exception will be handled.

A throws clause tells the compiler that "Yup, it died, but I will not
handle it". So the next method up the call stack is inspected. At some
point there will need to be a catch for that exception. The method
without the throws is the one that will have that catch, enforced by the
compiler.

And if you decide to handle it lower down the chain (via a catch), then
the compiler tells you that your throws is not being thrown. Again, it
forces YOU to re-think your error handling scheme.

I really like when I can get the compiler to locate my mistakes for me :-)
nukleus
2007-02-10 04:04:30 UTC
Permalink
Post by buggy
Post by Robbert Haarman
<insightful comments about using exceptions>
+1
Post by Robbert Haarman
However, James's original question was about the trows clause, and the
fact that you have to explicitly list the checked exceptions that a
method throws. In other words, it's not about the utility of exceptions
in general, but about the utility vs. burden of the throws clause.
I particularly dislike the trows clause, and the fact that you have to
add and update throms clauses on all methods that call a certain method,
when these methods are not interested in handling an exceptions
throwable by a "lower" method. However, I am curious what other people,
particularly people who actually _like_ Java, think about the issue.
I like the throws clause. Yes when you add a new exception deep within a
call stack, you must then add a throws clause up the chain.
This is a good thing.
By forcing you to add throws clauses, the language forces YOU to
determine where the exception will be handled.
A throws clause tells the compiler that "Yup, it died, but I will not
handle it". So the next method up the call stack is inspected. At some
point there will need to be a catch for that exception. The method
without the throws is the one that will have that catch, enforced by the
compiler.
And if you decide to handle it lower down the chain (via a catch), then
the compiler tells you that your throws is not being thrown. Again, it
forces YOU to re-think your error handling scheme.
I really like when I can get the compiler to locate my mistakes for me :-)
Yep, and not only mistakes,
but HELP you to pay attention to error conditions.
Simon
2007-02-07 14:17:14 UTC
Permalink
Post by Alex Hunsley
Post by James Harris
In terms of code maintenance, if dd could once throw a given exception
but now, because the relevant code has been removed, it cannot does cc
still need to provide for handling the exception simply /because/ it
is listed in dd's throws clause?
Java complains (compile error) if you declare a method as throwing a
checked exception when in fact it doesn't. So your above situation can't
happen - it won't compile.
It will, since overriding methods in subclasses could throw the exception. One
thing that does not compile is catching an exception that is not thrown. The
first method compiles, the second does not:

public class Test {

public void testThrows() throws java.io.FileNotFoundException {
}

public void testCatch() {
try {
System.out.println("Test");
} catch (java.io.FileNotFoundException e) {
e.printStackTrace();
}
}

}
Alex Hunsley
2007-02-07 23:14:12 UTC
Permalink
Post by Simon
Post by Alex Hunsley
Post by James Harris
In terms of code maintenance, if dd could once throw a given exception
but now, because the relevant code has been removed, it cannot does cc
still need to provide for handling the exception simply /because/ it
is listed in dd's throws clause?
Java complains (compile error) if you declare a method as throwing a
checked exception when in fact it doesn't. So your above situation can't
happen - it won't compile.
It will, since overriding methods in subclasses could throw the exception. One
thing that does not compile is catching an exception that is not thrown. The
public class Test {
public void testThrows() throws java.io.FileNotFoundException {
}
public void testCatch() {
try {
System.out.println("Test");
} catch (java.io.FileNotFoundException e) {
e.printStackTrace();
}
}
}
D'oh! Of course, you're right. I was think of exactly what you detail in
your example there (trying to catch an unthrown exception) and got it
the wrong way round!
thanks,
lex
Marcin 'Qrczak' Kowalczyk
2007-02-07 10:32:50 UTC
Permalink
Post by James Harris
Is there really value in Java's behaviour?
Some people believe so. Others claim that the cure is worse than the
disease. I think it's not worth the trouble.

http://radio.weblogs.com/0122027/stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html
http://www.mindview.net/Etc/Discussions/CheckedExceptions
http://www.artima.com/intv/handcuffs2.html

See also: http://java.sun.com/javase/6/docs/api/java/lang/ThreadDeath.html
"The class ThreadDeath is specifically a subclass of Error rather than
Exception, even though it is a "normal occurrence", because many
applications catch all occurrences of Exception and then discard the
exception."

It's easy to imagine *why* many applications are tempted to catch all
occurrences of Exception and then discard the exception.
--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Chris Uppal
2007-02-07 15:58:35 UTC
Permalink
Post by Marcin 'Qrczak' Kowalczyk
Post by James Harris
Is there really value in Java's behaviour?
Some people believe so. Others claim that the cure is worse than the
disease. I think it's not worth the trouble.
I agree with both those assertions and (fwiw) I largely share your opinion.

They way the system has been set up, a throws clause is a promise /not/ to
throw any (checked) exception which is not on the list. There is some value in
that, but it also puts a burden on the designer of the superclass to anticipate
all possible subclasses (or else s/he is making a promise that cannot or should
not be kept). Another way of looking at it is that it couples the design of
the superclass to its subclasses.

For instance a file-backed implementation of java.lang.List cannot throw
IOExceptions relating to failed filesystem operations (no such file, wrong
permissions, etc). So the implementer is forced into one of several unwelcome
options. One is just to swallow the errors. Not a good idea ;-) Another is
to wrap them in unchecked exceptions -- but if we have to do that often then
clearly the idea of having checked exceptions wasn't too hot in the first
place. Perhaps the best option is for the "standard" List operations to throw
unchecked exceptions, but for there to be a different interface which throws
checked exceptions -- thus clients which "know" that the List is actually a
DiskBackedList will be able to use the alternate API and thus be alerted to the
possibility of important failures.

Which suggests that a better scheme for checked exceptions would have been to
allow a method to override another method and declare that it throws /more/
exceptions than the parent. Code which handled the object via a reference of
the superclass type would not "know" about the extra possible exceptions -- and
thus would treat them as if they were unchecked. But code which handled the
object via a reference of the subclass type /would/ see the extended
definition, and thus the compiler could enforce checking in just the way it
does in real Java.

Incidentally, all this enforced checking happens only in the compiler, so it
would be possible to change or relax the rules without changing the JVM spec
(very unwelcome); or to use different rules in a Java-like language which
targeted the same JVM.

-- chris
Alex Hunsley
2007-02-07 23:26:17 UTC
Permalink
Post by Chris Uppal
Post by Marcin 'Qrczak' Kowalczyk
Post by James Harris
Is there really value in Java's behaviour?
Some people believe so. Others claim that the cure is worse than the
disease. I think it's not worth the trouble.
I agree with both those assertions and (fwiw) I largely share your opinion.
They way the system has been set up, a throws clause is a promise /not/ to
throw any (checked) exception which is not on the list. There is some value in
that, but it also puts a burden on the designer of the superclass to anticipate
all possible subclasses (or else s/he is making a promise that cannot or should
not be kept). Another way of looking at it is that it couples the design of
the superclass to its subclasses.
For instance a file-backed implementation of java.lang.List cannot throw
IOExceptions relating to failed filesystem operations (no such file, wrong
permissions, etc). So the implementer is forced into one of several unwelcome
options. One is just to swallow the errors. Not a good idea ;-) Another is
to wrap them in unchecked exceptions -- but if we have to do that often then
clearly the idea of having checked exceptions wasn't too hot in the first
place.
Another possibility is throwing a wrapped checked exception. Obviously,
that would expose some details of what was going on in the
implementation, but at least the code handling the wrapped exception
knows that something went wrong, and has access to the actual 'cause'
exception inside, if it is interested....
Bent C Dalager
2007-02-08 10:54:14 UTC
Permalink
Post by Chris Uppal
They way the system has been set up, a throws clause is a promise /not/ to
throw any (checked) exception which is not on the list. There is some value in
that, but it also puts a burden on the designer of the superclass to anticipate
all possible subclasses (or else s/he is making a promise that cannot or should
not be kept). Another way of looking at it is that it couples the design of
the superclass to its subclasses.
I would rather think that the superclass designer should only look at
what sort of conceptual problems could arise from the superclass and
introduce checked exceptions for those. Implementors of subclasses
will then be left with the task of mapping their lower-level problems
to the superclass' higher-level concepts but this shouldn't be too
unproblematic.

A general List specification may be declared to throw
CouldNotInsertExceptions and
ElementUnreadableExceptions. Implementations of the list will know to
map their IOExceptions or whatever to those higher-level conditions.

Of course, having all methods in the superclass throwing some sort of
checked exception can get tedious for clients of that class.
Post by Chris Uppal
For instance a file-backed implementation of java.lang.List cannot throw
IOExceptions relating to failed filesystem operations (no such file, wrong
permissions, etc). So the implementer is forced into one of several unwelcome
options. One is just to swallow the errors. Not a good idea ;-) Another is
to wrap them in unchecked exceptions -- but if we have to do that often then
clearly the idea of having checked exceptions wasn't too hot in the first
place. Perhaps the best option is for the "standard" List operations to throw
unchecked exceptions, but for there to be a different interface which throws
checked exceptions -- thus clients which "know" that the List is actually a
DiskBackedList will be able to use the alternate API and thus be alerted to the
possibility of important failures.
We might have two different types of List: UnreliableList and
ReliableList. The former would potentially throw checked exceptions
from all its methods since it is expected that it may occassionally be
cut off from its data source (file-based, db-based, network-based,
etc.) whileas the latter would not as we expect any problems in
accessing its data would be sufficiently catastrophic to grind the
rest of the system to a halt anyway (RAM-based storage).

Cheers
Bent D
--
Bent Dalager - ***@pvv.org - http://www.pvv.org/~bcd
powered by emacs
Andy Dingley
2007-02-07 16:56:25 UTC
Permalink
/why/ force the programmer to declare what a method /may/ throw?
I see this as being related to the logic behind the "structured
programming" movement. (ask your Grandad, it pre-dated OOP) and the
whole "GOTOs considered harmful" concept.

The idea was that big programs were too complex to understand, so that
instead you'd break them into smaller programs that could be treated
as black boxes, and this required that such boxes could _only_ route
program flow along a few well-defined pathways - ideally one way in,
one way out. The enemy of the day was "spaghetti code" where GOTO
could jump from any location to any other location.

Requiring the thrown exceptions to be explicitly listed (along with
the normal end of block execution path) will list the set of all
possible output routes from a block of code. This allows some black-
box analysis of the overall program, without worrying too much about
what happens inside the box.
Arthur J. O'Dwyer
2007-02-07 20:18:01 UTC
Permalink
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer to
declare what a method /may/ throw?
To quote one: "If you write a method that throws an exception, then
the Java compiler wil require that you do one of two things: you must
either declare that the method throws the exception using the 'throws'
keyword, or else you must provide a catch exception handler to catch
that exception." - Java Programming Explorer.
Is there really value in Java's behaviour? Or is this an unnecessary
burden on the programmer? Why not simply accept exceptions can be
thrown which are not listed, and deal with them in the innermost catch
clause which matches?
You probably know that C++ treats exceptions that way, although I
think they just did it that way so that you could mix old exceptionless
(unexceptional?) code with new exception-throwing code.
Also, if you make exception specifications part of the function's
"prototype", it would be one more thing to annoy programmers who use
function pointers. It's bad enough that I can't pass 'strcmp' as the
fourth argument to 'qsort'; now you're telling me I can't even pass
'int blah(const void *, const void *) throws(Bletch)' because its
exception specification doesn't match what 'qsort' expects?

But those considerations are all due to C++'s legacy from C, and I
don't think they apply to Java except insofar as a lot of Java programmers
came over from C and C++ in the early days. Exception handling is still
arcane enough that "because C++ does it that way" isn't a winning
argument, the way it is with operator precedence or control structures. :)


So, what are the benefits of explicitly declaring exception
specifications? First, psychological reasons; I recommend that
everyone read Tom Cargill's "Exception Handling: A false sense of
security", from 1994, which demonstrates how easy it is to forget
what you're doing when you write code involving exceptions.
http://www.awprofessional.com/content/images/020163371x/supplements/Exception_Handling_Article.html
Clearly, having to write exception specifications for all his member
functions would not have saved Reed; but might it have made him
think a little bit harder, and maybe eliminated one or two bugs
out of a dozen?

Second, there might be technical reasons to prefer that functions
declare anything they expect to catch, throw, or pass through.
Obviously we don't /need/ that information, because if we did, it would
be impossible to compile C++! :) But it might help. See this snippet
of "exception-handling" code in C, which needs the concept of a "rethrow"
clause to be implementable in ISO standard C:

http://en.wikipedia.org/wiki/Talk:Setjmp.h#Nested_catch_blocks

So if you're translating Java to ISO C, it might be useful. ;)

[...]
Post by James Harris
In terms of code maintenance, if dd could once throw a given exception
but now, because the relevant code has been removed, it cannot does cc
still need to provide for handling the exception simply /because/ it
is listed in dd's throws clause?
In terms of code maintenance, heck yes! If the programmer has removed
DD's ability to throw E, he should also have changed DD's exception
specification. If the compiler can warn him about his oversight, that's
a good thing in my book.

-Arthur
Tor Iver Wilhelmsen
2007-02-15 18:10:14 UTC
Permalink
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer
to declare what a method /may/ throw?
Because it's compiler-enforced documentation. Why do you want to move
stuff from the source to the documentation?
Post by James Harris
Is there really value in Java's behaviour?
Yes. In the same way there is value in the type safety of a strongly
typed language over an untyped one, for instance.
Post by James Harris
Or is this an unnecessary burden on the programmer?
For "burden" I read "having to type more than I would in a cryptic
PL/I program". :) Every piece of "simplification" or "syntactic sugar"
means less to type - but more to "not type", ie. having to be aware of
as implicit instead of explicit.

Case in point: Auto-boxing in Java. Earlier you could pinpoint a
NullPointerException to the use of the dot operator on a null
reference in your code (or an explicit throw). No longer! Now you can
also have a NPE when dereferencing an int that really is an Integer,
because of the *implicit* call to Integer.intValue() you did not write
but the compiler added for you.
Post by James Harris
Why not simply accept exceptions can be thrown which are not listed,
and deal with them in the innermost catch clause which matches?
Because you then just move "this methods throws FooException" from the
code to (hopefully) the documentation. Hint: You want as many
compile-time checks as possible to avoid runtime checks - or errors.
Post by James Harris
Conversely, if there is a chain of methods: aa calls bb calls cc calls
dd, and dd declares that it throws FileNotFoundException, if we don't
want to handle it in cc do we need to declare that it also throws
FileNotFoundException... and so on through callers to cc etc?
Yes, because you need to document to the users of a method how it
behaves. And throws clauses is compiler-enforced and thus better than
prose.
Post by James Harris
In terms of code maintenance, if dd could once throw a given
exception but now, because the relevant code has been removed, it
cannot does cc still need to provide for handling the exception
simply /because/ it is listed in dd's throws clause?
Yes.
James Harris
2007-02-18 22:50:03 UTC
Permalink
Post by Tor Iver Wilhelmsen
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer
to declare what a method /may/ throw?
Because it's compiler-enforced documentation. Why do you want to move
stuff from the source to the documentation?
There have been some excellent replies to my original query (which are
much appreciated). My view now is that enforcing exception checking in
the way that Java does is not desirable. I guess I felt that before
but now have good reasons!

One valid argument for Java's enforcing is that it documents part of
the subprogram's interface. Isn't this, however, ultimately incomplete
as Errors can occur which are undeclared?

My main objections to Java's way is that if aa calls bb calls cc ...
calls zz and I want to handle zz's errors in aa I still have to either
declare them in all intervening modules or catch a generic Exception
superclass and possibly encapsulate them in another object. The latter
is a kludge, IMHO. The former unfortunately obscures the program logic
and intention with foreign constructs or "mechanism."

It doesn't seem unreasonable to accept that a given subprogram can
generate arbitrary errors. Rather than Java's approach I think I would
rather the language generate the list of possible exceptions after
examining the code and subprograms. This could indeed be part of the
documentation but I don't want to require that each exception be
listed in every module. That seems to be going too far.
Post by Tor Iver Wilhelmsen
Post by James Harris
Is there really value in Java's behaviour?
Yes. In the same way there is value in the type safety of a strongly
typed language over an untyped one, for instance.
Type safety is valid but the analogy can be taken too far. For
example, Pascal regards the dimensions of an array as part of the
type. Sure, this ties the language down more but is an unnecessary
restriction.

...
Post by Tor Iver Wilhelmsen
Post by James Harris
In terms of code maintenance, if dd could once throw a given
exception but now, because the relevant code has been removed, it
cannot does cc still need to provide for handling the exception
simply /because/ it is listed in dd's throws clause?
Yes.
This seems a good case in point of why Java's approach is wrong. Maybe
there is a better way.
Lew
2007-02-18 23:04:49 UTC
Permalink
Post by James Harris
This seems a good case in point of why Java's approach is wrong. Maybe
there is a better way.
You certainly are entitled to your opinion.

I prefer to take the approach that "Java's approach is what it is", without
"wrong" or "right". Is it a perfect computer language? Is there any such thing?

Java requires that checked exceptions be declared in a method's declaration.
It does not require that any method you write should declare a checked
exception. It is a language feature that you are free not to use.

I agree with you that there are inconveniences to the exception idiom. Calling
such things "wrong" without regard for their purpose is cute but not very
useful. Even if they are "wrong", they exist in Java as they exist in Java.

The only "wrong" thing in Java is that which violates its own definition,
i.e., the JLS. The evaluations we can make as programmers are;

- "I like / dislike that feature", to which I would reply, "Great!"
- "This feature could be expressed in a different language with greater
convenience to the programmer", to which I reply, "You make a very good case."
- "This feature is / is not worth the effort in the particular situation ...",
to which I reply, "That is a very sensible engineering decision."

But "wrong" or "right"? Not engineering evaluations.

For my part, I aver that Java, and in particular its exception idioms, are
very useful in my own work. To which I would expect no more than a general
feeling of comradely satisfaction that someone was getting programming done.

- Lew
Chris Uppal
2007-02-19 13:54:41 UTC
Permalink
Calling such things "wrong" without regard for their purpose is cute but
not very useful. Even if they are "wrong", they exist in Java as they
exist in Java.
I think you are missing the OP's point. His interest (as I understand it)
isn't in how to use Java effectively, but in how to design programming
languages. Which is why he asked for our experiences as users of one
experiment in design -- namely checked exceptions in Java.

-- chris
Robbert Haarman
2007-02-19 22:30:17 UTC
Permalink
Post by Chris Uppal
I think you are missing the OP's point. His interest (as I understand it)
isn't in how to use Java effectively, but in how to design programming
languages. Which is why he asked for our experiences as users of one
experiment in design -- namely checked exceptions in Java.
Actually, not even checked exceptions in general, but, specifically, the
mandatory throws clause (see the subject line). The distinction is
important; checked exceptions can exist without the throws clause.

Regards,

Bob
--
Perilous to all of us are the devices of an art deeper than we ourselves
possess.
-- Gandalf the Grey [J.R.R. Tolkien, "Lord of the Rings"]
Lew
2007-02-19 23:49:31 UTC
Permalink
Post by Robbert Haarman
Actually, not even checked exceptions in general, but, specifically, the
mandatory throws clause (see the subject line). The distinction is
important; checked exceptions can exist without the throws clause.
?

The very definition of a "checked" exception is one that must be declared in
the throws clause of the method that throws it.

Consider this quote from
<http://www.developer.com/java/article.php/1455891>:

<quote>
Checked exceptions

All exceptions instantiated from the Exception class, or from subclasses of
Exception other than RuntimeException and its subclasses must either be:

* Handled with a try block followed by a catch block, or
* Declared in a throws clause of any method that can throw them

In other words, checked exceptions cannot be ignored when you write the code
in your methods. According to Flanagan, the exception classes in this
category represent routine abnormal conditions that should be anticipated and
caught to prevent program termination.

Checked by the compiler

Your code must anticipate and either handle or declare checked exceptions.
Otherwise, your program won't compile. (These are exception types that are
checked by the compiler.)
</quote>

For the hard truth, see the JLS, 11.2:
<http://java.sun.com/docs/books/jls/third_edition/html/exceptions.html#44121>

- Lew
Robbert Haarman
2007-02-20 00:04:44 UTC
Permalink
Post by Lew
Post by Robbert Haarman
Actually, not even checked exceptions in general, but, specifically, the
mandatory throws clause (see the subject line). The distinction is
important; checked exceptions can exist without the throws clause.
?
The very definition of a "checked" exception is one that must be declared
in the throws clause of the method that throws it.
Consider this quote from
<quote>
Checked exceptions
All exceptions instantiated from the Exception class, or from subclasses of
* Handled with a try block followed by a catch block, or
* Declared in a throws clause of any method that can throw them
Well, of course. But we are discussing whether or not that latest point
is good language design. So, I assumed that, for purposes of this
discussion, a checked exception is one that must be handled explicitly
by the program (i.e. by a catch block). This can certainly be
accomplished without requiring the exception to be mentioned in any
throws clause.

Regards,

Bob
--
67.7234597% of statistics are made up.
Lew
2007-02-20 00:10:37 UTC
Permalink
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
Actually, not even checked exceptions in general, but, specifically, the
mandatory throws clause (see the subject line). The distinction is
important; checked exceptions can exist without the throws clause.
?
The very definition of a "checked" exception is one that must be declared
in the throws clause of the method that throws it.
Well, of course. But we are discussing whether or not that latest point
is good language design. So, I assumed that, for purposes of this
discussion, a checked exception is one that must be handled explicitly
by the program (i.e. by a catch block). This can certainly be
accomplished without requiring the exception to be mentioned in any
throws clause.
Yes, you are right, by throwing an unchecked exception, which Java allows.

My point is that Java allows the programmer the choice of throwing arbitrary
exceptions that the API client need not catch, but may simply crash in the
face thereof, just as you say you want a language to allow. Ergo, nothing
wrong with Java.

Likewise, when the programmer wants to require handling of a certain
exception, they can declare a checked exception, thereby strenghthening the
API by making sure at compile time its clients will not be fubared by an
unexpected exception. So for times when checked exceptions are better, Java
allows that, too. Ergo, nothing wrong with Java.

Since the throws clause is not mandatory, the conclusion that a mandatory
throws clause makes Java bad must be false.

- Lew
Robbert Haarman
2007-02-20 00:31:45 UTC
Permalink
Post by Lew
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
Actually, not even checked exceptions in general, but, specifically, the
mandatory throws clause (see the subject line). The distinction is
important; checked exceptions can exist without the throws clause.
?
The very definition of a "checked" exception is one that must be declared
in the throws clause of the method that throws it.
Well, of course. But we are discussing whether or not that latest point
is good language design. So, I assumed that, for purposes of this
discussion, a checked exception is one that must be handled explicitly
by the program (i.e. by a catch block). This can certainly be
accomplished without requiring the exception to be mentioned in any
throws clause.
Yes, you are right, by throwing an unchecked exception, which Java allows.
No, that's not the same. An unchecked exception is one that the program
is not required to handle explicitly. What I am talking about is an
excetion which the program _is_ required to handle explicitly. I am
saying this requirement can be enforced without requiring methods that
propagate the exception up the call chain to list the exception in a
throws clause.

For example, if I write:

public void foo() {
// call something that could throw an IOException
}

public void bar() {
// call foo
}

public static void main(String arg[]) {
bar();
}

Even though I have not written "throws IOException", the compiler can
infer that foo and bar can throw this exception, and that the program
does not catch that exception. If IOException is one that must be
handled (what I have called a checked exception), the compiler can
reject the program. Thus, exceptions that a program is required to
handle can exist without the throws clause. This is the point I was
trying to make earlier.

Regards,

Bob
--
Using a (signed) 64-bit value introduces a new wraparound date in about
290 billion years, on Sunday, December 4, 292,277,026,596. However, this
problem is not widely regarded as a pressing issue.

-- Wikipedia, Year 2038 Problem
Lew
2007-02-20 00:50:44 UTC
Permalink
Post by Robbert Haarman
Even though I have not written "throws IOException", the compiler can
infer that foo and bar can throw this exception, and that the program
does not catch that exception. If IOException is one that must be
handled (what I have called a checked exception), the compiler can
reject the program. Thus, exceptions that a program is required to
handle can exist without the throws clause. This is the point I was
trying to make earlier.
I see what you mean.

If I understand you correctly, the complaint with Java is the notational
overhead of actually having to put the words "throws Blah" in the method
signature.

I think that the "self-documentation" feature of those words would offset the
overhead for many programmers, myself included, but I agree that those words
are overhead. You are most likely correct that some Java-like language could
have checked exceptions in the way that you describe.

There is a purpose for that overhead in Java. The question boils down to
whether the purpose is sufficient to justify the overhead. You think it is
not. I respect that.

- Lew
James Harris
2007-02-21 22:01:00 UTC
Permalink
Post by Lew
Post by Robbert Haarman
Even though I have not written "throws IOException", the compiler can
infer that foo and bar can throw this exception, and that the program
does not catch that exception. If IOException is one that must be
handled (what I have called a checked exception), the compiler can
reject the program. Thus, exceptions that a program is required to
handle can exist without the throws clause. This is the point I was
trying to make earlier.
I see what you mean.
If I understand you correctly, the complaint with Java is the notational
overhead of actually having to put the words "throws Blah" in the method
signature.
I think that the "self-documentation" feature of those words would offset the
overhead for many programmers, myself included, but I agree that those words
are overhead. You are most likely correct that some Java-like language could
have checked exceptions in the way that you describe.
There is a purpose for that overhead in Java. The question boils down to
whether the purpose is sufficient to justify the overhead. You think it is
not. I respect that.
I haven't caught up with all the posts yet so this may have been
discussed but to come back to my original point - and my original and
only complaint - about Java's syntax: if I have a /chain/ of methods,
want to detect errors in the lowest and handle them in the highest
doesn't this mean there is a greater 'overhead' in method signatures
than your post suggests? Doesn't each and every intervening method
need the same throws clause?

If the lower methods declare they will throw just five checked
exceptions don't these all need declaring in every intervening method?
If there are ten intervening methods isn't that 50 exceptions to add?
The situation is, in fact, worse than this suggests as each method may
well call more than one other method, each of which throws its own
errors.

In other words my challenge on Java is that checked exceptions don't
seem to scale well. I understand this issue can be "fixed" by various
means but these are not natural parts of the language.
Lew
2007-02-21 23:15:33 UTC
Permalink
Post by James Harris
I haven't caught up with all the posts yet so this may have been
discussed but to come back to my original point - and my original and
only complaint - about Java's syntax: if I have a /chain/ of methods,
want to detect errors in the lowest and handle them in the highest
doesn't this mean there is a greater 'overhead' in method signatures
than your post suggests? Doesn't each and every intervening method
need the same throws clause?
If the lower methods declare they will throw just five checked
exceptions don't these all need declaring in every intervening method?
If there are ten intervening methods isn't that 50 exceptions to add?
The situation is, in fact, worse than this suggests as each method may
well call more than one other method, each of which throws its own
errors.
In other words my challenge on Java is that checked exceptions don't
seem to scale well. I understand this issue can be "fixed" by various
means but these are not natural parts of the language.
That would not be the usual handling of exceptions, but anyway it isn't 50
exceptions, it's five exceptions on ten methods.

This is similar to the overhead of declaring the parameters for each of the
ten methods.

If you wrote a chain of methods that rethrow checked exceptions all the way
up, that was a design decision and presumably there was a good reason for it.
Other idioms exists, however, so this choice is not mandatory. The "fixes"
are, indeed, a "natural part" of Java, since the natural idioms in Java are:

- Catch and handle the exception - no rethrow.
- Catch and rethrow, or simply pass through a checked exception - the scenario
you did not like but is really just fine.
- Catch a checked exception and wrap in an unchecked one, then throw the
unchecked exception - no throws clause needed above this.
- Catch the five exceptions at the lowest level, log them, then wrap in a
single, application-specific checked exception that all higher methods recognize.

This last is probably the most common. Once you've handled the exception at
the lowest level, you really don't care any more whether it was a
ServletException or an IOException; at that point it is just a MyAppException
with the original Throwable as its cause.

All these are quite "natural" and most of them reduce the overhead of the
throws clause.

Personally, I think all this fuss over a little extra typing for the throws
clause is a combination of laziness and not understanding the exception idioms.

- Lew
Arne Vajhøj
2007-02-20 01:10:04 UTC
Permalink
Post by Robbert Haarman
No, that's not the same. An unchecked exception is one that the program
is not required to handle explicitly. What I am talking about is an
excetion which the program _is_ required to handle explicitly. I am
saying this requirement can be enforced without requiring methods that
propagate the exception up the call chain to list the exception in a
throws clause.
public void foo() {
// call something that could throw an IOException
}
public void bar() {
// call foo
}
public static void main(String arg[]) {
bar();
}
Even though I have not written "throws IOException", the compiler can
infer that foo and bar can throw this exception, and that the program
does not catch that exception. If IOException is one that must be
handled (what I have called a checked exception), the compiler can
reject the program. Thus, exceptions that a program is required to
handle can exist without the throws clause. This is the point I was
trying to make earlier.
That only work for toy examples.

main, bar and foo may be in different files.

Different projects/libraries.

Arne
Robbert Haarman
2007-02-20 01:14:56 UTC
Permalink
Post by Arne Vajhøj
Post by Robbert Haarman
No, that's not the same. An unchecked exception is one that the program
is not required to handle explicitly. What I am talking about is an
excetion which the program _is_ required to handle explicitly. I am
saying this requirement can be enforced without requiring methods that
propagate the exception up the call chain to list the exception in a
throws clause.
public void foo() {
// call something that could throw an IOException
}
public void bar() {
// call foo
}
public static void main(String arg[]) {
bar();
}
Even though I have not written "throws IOException", the compiler can
infer that foo and bar can throw this exception, and that the program
does not catch that exception. If IOException is one that must be
handled (what I have called a checked exception), the compiler can
reject the program. Thus, exceptions that a program is required to
handle can exist without the throws clause. This is the point I was
trying to make earlier.
That only work for toy examples.
main, bar and foo may be in different files.
Different projects/libraries.
Yes, but what is the problem with that? As far as I know, there is
nothing preventing the compiler from putting exception information in
the class files. Once the information about which exceptions a method
can throw has been inferred, it can be treated exactly the same way Java
now treats the information in throws clauses.

Regards,

Bob
--
This sentence no verb
Arne Vajhøj
2007-02-20 01:23:37 UTC
Permalink
Post by Robbert Haarman
Post by Arne Vajhøj
That only work for toy examples.
main, bar and foo may be in different files.
Different projects/libraries.
Yes, but what is the problem with that? As far as I know, there is
nothing preventing the compiler from putting exception information in
the class files. Once the information about which exceptions a method
can throw has been inferred, it can be treated exactly the same way Java
now treats the information in throws clauses.
Oh, so you do want throws in the class files - you just don't want
it the source code ?

Arne
Robbert Haarman
2007-02-20 10:33:39 UTC
Permalink
Post by Arne Vajhøj
Oh, so you do want throws in the class files - you just don't want
it the source code ?
In short, yes.

The class files should contain whatever is necessary to make things
work. If that includes some sort of throws clause (which I think it
must, in order to support exceptions that must be handled explicitly),
then that is fine with me.

Now, the source code is different, because the source code is what I
have to type in. Mandating (for exceptions that must be handled
explicitly) throws clauses in the source code has an affect (which I
believe to be net negative) on programmer productivity.

Lew has the right of it: the throws clause (in the source code)
represents a trade-off. Clearly, some people prefer the trade-off to me
made one way, and other people prefer it to made the other way.

What I said about the compiler being able to verify that exceptions are
handled by the program without requiring throws clauses means that this
verification is not part of the trade-off. As far as I can see, the
trade-off is between the amount of code that needs to be written,
maintained, and modified, and having a bit of extra information in the
source code (rather than, say, in the documentation). I will also note
that (as has been stated in this thread), the throws clause can be out
of sync with what exceptions can _really_ be thrown. If, instead, the
list of exceptions that can be thrown is inferred, it will always be
correct.

Regards,

Bob
--
How to get $$$$ quickly:

1. Hold down the <shift> key
2. Type 4444
Lew
2007-02-20 13:11:40 UTC
Permalink
Post by Robbert Haarman
Lew has the right of it: the throws clause (in the source code)
represents a trade-off. Clearly, some people prefer the trade-off to me
made one way, and other people prefer it to made the other way.
And regardless of preference, Java does what Java does.

- Lew
Chris Uppal
2007-02-20 16:39:51 UTC
Permalink
Post by Robbert Haarman
I will also note
that (as has been stated in this thread), the throws clause can be out
of sync with what exceptions can _really_ be thrown. If, instead, the
list of exceptions that can be thrown is inferred, it will always be
correct.
That, I believe, is untrue, and is probably the reason why Java works the way
it does.

The approach the Java typechecker takes is /always/ that each method contains
exactly the information needed to know whether it can be called correctly (up
to the notion of "correctness" implemented by the typechecker). That goes for
argument types, return type, static-or-not, and so on (if there is any more).
Including the list of checked exeptions it can throw. It never does
cross-method type inference.

I think the strongest reason for that is simplicity (of design and of semantics
as seen by programmers). But another strong technical reason is that type
inference is either impossible or very near impossible in the presence of
dynamic code loading. Java is /not/ a static language (however much javac
tries to pretend it is), and for a method like
aMethod(AType argument)
{
argument.doSomething();
}
the compiler just cannot know what concrete code will be executed by the call
to doSomething(). To do that requires whole-program analysis, but there /is/ no
"whole program" in Java...

(I believe that the combination of dynamic code loading, type inference, and
static type safety is an active topic of research in the functional language
community -- but that isn't my field.)

So, while the compiler could do some limited inference, it can't do a proper
job, and trying to do so would make Java's semantics significantly more complex
with little or no benefit to the end-user (the programmer). Hence the strategy
of avoiding type inference, and so of requiring explicit type annotations to
describe every relevant aspect of every method. The "throws" clause is just a
special case of that rule.

-- chris
Arne Vajhøj
2007-02-21 03:09:58 UTC
Permalink
Post by Robbert Haarman
Post by Arne Vajhøj
Oh, so you do want throws in the class files - you just don't want
it the source code ?
In short, yes.
The class files should contain whatever is necessary to make things
work. If that includes some sort of throws clause (which I think it
must, in order to support exceptions that must be handled explicitly),
then that is fine with me.
Now, the source code is different, because the source code is what I
have to type in. Mandating (for exceptions that must be handled
explicitly) throws clauses in the source code has an affect (which I
believe to be net negative) on programmer productivity.
But why make the functionality hidden for the programmer ?

He will have the choice of either using compiler exceptions to
figure out what to catch or to study the entire code path
(which will often not be possible).
Post by Robbert Haarman
What I said about the compiler being able to verify that exceptions are
handled by the program without requiring throws clauses means that this
verification is not part of the trade-off. As far as I can see, the
trade-off is between the amount of code that needs to be written,
maintained, and modified, and having a bit of extra information in the
source code (rather than, say, in the documentation). I will also note
that (as has been stated in this thread), the throws clause can be out
of sync with what exceptions can _really_ be thrown. If, instead, the
list of exceptions that can be thrown is inferred, it will always be
correct.
It is not even possible.

What should the compiler do for:

MyInterface o = (MyInterface)Class.forName("MyClass").newInstance();

?

MyInterface does not contain any exception throwing code (it does
not contain any code at all).

Arne
Robbert Haarman
2007-02-21 05:40:44 UTC
Permalink
Post by Arne Vajhøj
Post by Robbert Haarman
Post by Arne Vajhøj
Oh, so you do want throws in the class files - you just don't want
it the source code ?
In short, yes.
The class files should contain whatever is necessary to make things
work. If that includes some sort of throws clause (which I think it
must, in order to support exceptions that must be handled explicitly),
then that is fine with me.
Now, the source code is different, because the source code is what I
have to type in. Mandating (for exceptions that must be handled
explicitly) throws clauses in the source code has an affect (which I
believe to be net negative) on programmer productivity.
But why make the functionality hidden for the programmer ?
What functionality?
Post by Arne Vajhøj
Post by Robbert Haarman
What I said about the compiler being able to verify that exceptions are
handled by the program without requiring throws clauses means that this
verification is not part of the trade-off. As far as I can see, the
trade-off is between the amount of code that needs to be written,
maintained, and modified, and having a bit of extra information in the
source code (rather than, say, in the documentation). I will also note
that (as has been stated in this thread), the throws clause can be out
of sync with what exceptions can _really_ be thrown. If, instead, the
list of exceptions that can be thrown is inferred, it will always be
correct.
It is not even possible.
MyInterface o = (MyInterface)Class.forName("MyClass").newInstance();
?
MyInterface does not contain any exception throwing code (it does
not contain any code at all).
Interfaces probably should be an exception to the rule in that the
programmer must specify the exception list. As you point out correctly,
there is no code the list could be inferred from.

Regards,

Bob
--
"It's often easier not to do something dumb then to do something smart."

-- mjr.
Arne Vajhøj
2007-02-22 01:42:21 UTC
Permalink
Post by Robbert Haarman
Post by Arne Vajhøj
Post by Robbert Haarman
Post by Arne Vajhøj
Oh, so you do want throws in the class files - you just don't want
it the source code ?
In short, yes.
The class files should contain whatever is necessary to make things
work. If that includes some sort of throws clause (which I think it
must, in order to support exceptions that must be handled explicitly),
then that is fine with me.
Now, the source code is different, because the source code is what I
have to type in. Mandating (for exceptions that must be handled
explicitly) throws clauses in the source code has an affect (which I
believe to be net negative) on programmer productivity.
But why make the functionality hidden for the programmer ?
What functionality?
That it can throw an exception.
Post by Robbert Haarman
Post by Arne Vajhøj
Post by Robbert Haarman
What I said about the compiler being able to verify that exceptions are
handled by the program without requiring throws clauses means that this
verification is not part of the trade-off. As far as I can see, the
trade-off is between the amount of code that needs to be written,
maintained, and modified, and having a bit of extra information in the
source code (rather than, say, in the documentation). I will also note
that (as has been stated in this thread), the throws clause can be out
of sync with what exceptions can _really_ be thrown. If, instead, the
list of exceptions that can be thrown is inferred, it will always be
correct.
It is not even possible.
MyInterface o = (MyInterface)Class.forName("MyClass").newInstance();
?
MyInterface does not contain any exception throwing code (it does
not contain any code at all).
Interfaces probably should be an exception to the rule in that the
programmer must specify the exception list. As you point out correctly,
there is no code the list could be inferred from.
And the same can be the case for abstract classes.

I like the consistency in the choice Java made.

Arne
James Harris
2007-02-21 22:20:57 UTC
Permalink
Post by Chris Uppal
Calling such things "wrong" without regard for their purpose is cute but
not very useful. Even if they are "wrong", they exist in Java as they
exist in Java.
I think you are missing the OP's point. His interest (as I understand it)
isn't in how to use Java effectively, but in how to design programming
languages. Which is why he asked for our experiences as users of one
experiment in design -- namely checked exceptions in Java.
[OP] Yes, that was my reason for raising this. Perhaps we should start
a thread in only c.l.m. Don't want to upset the Java folks too
much :-) In fact, I am trying to learn Java too and am intrigued, to
say the least, by how much people like this feature.
Robbert Haarman
2007-02-21 22:55:29 UTC
Permalink
Post by James Harris
[OP] Yes, that was my reason for raising this. Perhaps we should start
a thread in only c.l.m. Don't want to upset the Java folks too
much :-) In fact, I am trying to learn Java too and am intrigued, to
say the least, by how much people like this feature.
It's funny you should say that, because that has been my experience with
everything I don't like about Java.

FYI, Java was one of the first programming languages I learned (after
BASIC, x86 assembly and C), and, initially, I drank the Kool-Aid and
thought it was the greatest language in the world. Then, when I started
to learn other languages (PHP, Scheme, Common Lisp, Ruby, OCaml, among
others, in some order), I discovered that Java is fairly verbose and
rigid; there is One Right Way, and many things that can be expressed
elegantly in other languages look clumsy in Java.

There are certainly good arguments for the way things are done in Java
(for example, the One Right Way makes it much more likely that different
Java programmers can easily understand each other's code), and I think
Java is a passable programming language. Still, Java code often makes me
shudder. I am sure Java programmers shudder when they see some of my
code, too.

Regards,

Bob
--
TCPA: Where will you be allowed to go today?
James Harris
2007-02-21 23:16:03 UTC
Permalink
Post by Robbert Haarman
Post by James Harris
[OP] Yes, that was my reason for raising this. Perhaps we should start
a thread in only c.l.m. Don't want to upset the Java folks too
much :-) In fact, I am trying to learn Java too and am intrigued, to
say the least, by how much people like this feature.
It's funny you should say that, because that has been my experience with
everything I don't like about Java.
FYI, Java was one of the first programming languages I learned (after
BASIC, x86 assembly and C), and, initially, I drank the Kool-Aid and
thought it was the greatest language in the world. Then, when I started
to learn other languages (PHP, Scheme, Common Lisp, Ruby, OCaml, among
others, in some order), I discovered that Java is fairly verbose and
rigid; there is One Right Way, and many things that can be expressed
elegantly in other languages look clumsy in Java.
There are certainly good arguments for the way things are done in Java
(for example, the One Right Way makes it much more likely that different
Java programmers can easily understand each other's code), and I think
Java is a passable programming language. Still, Java code often makes me
shudder. I am sure Java programmers shudder when they see some of my
code, too.
Just out of curiosity, have you looked at and what do you think of
Python and Jython? I got a book on Jython this week and it looks a
much cleaner way to target the JVM. Before anyone complains, I'm not
saying it is "better" - it is clearly not in some cases - but maybe
its syntax would appeal more. To pick an example from the book:

Java: MyClass instance = (MyClass)list.get(2);
Jython: instance = list[2]
Lew
2007-02-21 23:29:28 UTC
Permalink
Post by Robbert Haarman
FYI, Java was one of the first programming languages I learned (after
BASIC, x86 assembly and C), and, initially, I drank the Kool-Aid and
thought it was the greatest language in the world. Then, when I started
to learn other languages (PHP, Scheme, Common Lisp, Ruby, OCaml, among
others, in some order), I discovered that Java is fairly verbose and
rigid; there is One Right Way, and many things that can be expressed
elegantly in other languages look clumsy in Java.
There are certainly good arguments for the way things are done in Java
(for example, the One Right Way makes it much more likely that different
Java programmers can easily understand each other's code), and I think
Java is a passable programming language. Still, Java code often makes me
shudder. I am sure Java programmers shudder when they see some of my
code, too.
Characterizing the style of the language as "The One Right Way" is cute, but
not apt. Many things I call "elegant" in Java you call "ugly". Many things
you call "elegant" in another language I call "loosey-goosey and unsafe".

À chacun son goût.

Like every language, Java was designed to support certain things at the
expense of others. You think Java is "verbose" and "rigid", which is your
right. Others might find those areas "self-documenting" and "sturdy".

Rigid is good when it's a guard rail at the edge of a precipice.

- Lew
Robbert Haarman
2007-02-22 00:10:37 UTC
Permalink
Post by Lew
Characterizing the style of the language as "The One Right Way" is cute,
See below.
Post by Lew
but not apt. Many things I call "elegant" in Java you call "ugly". Many
things you call "elegant" in another language I call "loosey-goosey and
unsafe".
À chacun son goût.
True. By the way, are people who don't speak French supposed to
understand that last sentence?
Post by Lew
Like every language, Java was designed to support certain things at the
expense of others.
That's where you are wrong. Java was designed to support certain things
and not others, and that's what makes it a One True Way language. Other
languages (albeit few) are designed to be multi-paradigm and let the
programmer choose which way to do things.
Post by Lew
You think Java is "verbose" and "rigid", which is your
right. Others might find those areas "self-documenting" and "sturdy".
Absolutely right.

Regards,

Bob
--
A man should practice what he preaches, but a man should also preach
what he practices.
-- Confucius
Arne Vajhøj
2007-02-22 01:44:19 UTC
Permalink
Post by Robbert Haarman
Post by Lew
Like every language, Java was designed to support certain things at the
expense of others.
That's where you are wrong. Java was designed to support certain things
and not others, and that's what makes it a One True Way language. Other
languages (albeit few) are designed to be multi-paradigm and let the
programmer choose which way to do things.
That is correct for most things.

But somewhat funny - not for exceptions, where Java actually did choose
multi paradigm.

Arne
Lew
2007-02-21 23:31:15 UTC
Permalink
Post by James Harris
Java: MyClass instance = (MyClass)list.get(2);
Actually, that would be

MyClass instance = list.get(2);

Assuming a correct declaration of list.
Post by James Harris
Jython: instance = list[2]
Where is the compile-time safety?

- Lew
Arthur J. O'Dwyer
2007-02-21 23:40:23 UTC
Permalink
[Xpost to c.l.j.help removed.]
Post by Lew
Post by James Harris
Java: MyClass instance = (MyClass)list.get(2);
Actually, that would be
MyClass instance = list.get(2);
Assuming a correct declaration of list.
If your list stores Objects, you need the downcast. (Unless this
aspect of Java has changed since four years ago, which is certainly
possible.) And a sufficiently general-purpose ADT must store Objects
(unless you're using a later Java, with generics or templates or
parameterized types or whatever it has now).
Post by Lew
Post by James Harris
Jython: instance = list[2]
Where is the compile-time safety?
It didn't go anywhere. "list[2]" contains exactly as many type
signifiers as "list.get(2)" --- in fact, it contains one more, in
that "[2]" signifies an array access, whereas any old object can
implement a "get" method.

-Arthur
Robbert Haarman
2007-02-22 00:02:42 UTC
Permalink
Post by Arthur J. O'Dwyer
[Xpost to c.l.j.help removed.]
Post by Lew
Post by James Harris
Java: MyClass instance = (MyClass)list.get(2);
Actually, that would be
MyClass instance = list.get(2);
Assuming a correct declaration of list.
If your list stores Objects, you need the downcast. (Unless this
aspect of Java has changed since four years ago, which is certainly
possible.) And a sufficiently general-purpose ADT must store Objects
(unless you're using a later Java, with generics or templates or
parameterized types or whatever it has now).
Java has had generics since 1.5 (or 5.0, or however its versioning
works). Basically, the type system is more ML-like now, but without type
inference.
Post by Arthur J. O'Dwyer
Post by Lew
Post by James Harris
Jython: instance = list[2]
Where is the compile-time safety?
Not there in Python, but I would like to note that in OCaml (and other
ML dialects), the above could be fully type-safe and statically
chcekable.

Regards,

Bob
--
Dude, where's my cdr?
Arne Vajhøj
2007-02-22 00:03:41 UTC
Permalink
Post by Arthur J. O'Dwyer
Post by Lew
Post by James Harris
Java: MyClass instance = (MyClass)list.get(2);
Actually, that would be
MyClass instance = list.get(2);
Assuming a correct declaration of list.
If your list stores Objects, you need the downcast. (Unless this
aspect of Java has changed since four years ago, which is certainly
possible.) And a sufficiently general-purpose ADT must store Objects
(unless you're using a later Java, with generics or templates or
parameterized types or whatever it has now).
It changed a couple of years ago with generics.

And that is the correct way of doing it today.

Arne
Arne Vajhøj
2007-02-22 01:49:36 UTC
Permalink
Post by Lew
Post by James Harris
Jython: instance = list[2]
Where is the compile-time safety?
Python has a different approach to types than
C/C++, Java, C# etc..

You can call that not type safe. But that concept
does not have the same negative meaning as in the
above mentioned languages.

Arne

Chris Smith
2007-02-18 23:36:14 UTC
Permalink
Post by James Harris
There have been some excellent replies to my original query (which are
much appreciated). My view now is that enforcing exception checking in
the way that Java does is not desirable. I guess I felt that before
but now have good reasons!
Whether it's desirable is, I suppose, a matter of who is doing the
desiring. I can attempt to address the other side of the issue, though,
so I will.
Post by James Harris
One valid argument for Java's enforcing is that it documents part of
the subprogram's interface.
It's not really about documenting. It's about generating knowledge
about your code and providing checks that you have written correct code.
Documentation is, at best, an incidental side-benefit.
Post by James Harris
My main objections to Java's way is that if aa calls bb calls cc ...
calls zz and I want to handle zz's errors in aa I still have to either
declare them in all intervening modules or catch a generic Exception
superclass and possibly encapsulate them in another object. The latter
is a kludge, IMHO.
I'd disagree with that assessment. It's certainly not a kludge. It may
be a pain at times, but it's exactly what you ought to expect to do.
Failing to throw exceptions that are appropriate for the interface
you're designing is poor abstraction. It is *exactly* like writing a
"lookupEmployee" method in a payroll system that returns a complete
payroll history and expects you to poke around and grab the information
about the employee from that. Both are examples of breaking abstraction
boundaries, and both are poor code.

To understand this bit of language design, you need to get your head
around the fact that declaring methods isn't some boilerplate thing that
you do because the compiler makes you. A method declaration is a
contract with a caller, and the fact that certain errors can be
generated is part of that contract. Another example: suppose that,
early on in the development of some system, you stub out some function.
You know that eventually you'll need to write that method. The throws
clause lets you ensure that the rest of your code properly handles the
error cases that will exist in that method later on. Even though you
have no implementation, you can still write to the contract.
Post by James Harris
It doesn't seem unreasonable to accept that a given subprogram can
generate arbitrary errors.
If that's true, then you need only throw Exception. There are, of
course, reasons why that is strongly discouraged... but they are EXACTLY
the same reasons that checking exceptions is considered desirable. For
example, I frequently declare main methods of test code with
"throws Exception" tacked onto the end; it makes sense to do so because,
as you said, it's okay for that code to generate arbitrary errors. It's
not generally okay for more significant pieces of software to generate
arbitrary errors; but if it is, then by all means you are free to add
"throws Exception" there, too.
Post by James Harris
Rather than Java's approach I think I would
rather the language generate the list of possible exceptions after
examining the code and subprograms.
This would, of course, provide none of the main benefit of checked
exceptions, which is the guarantee that error conditions are handled
(even across later changes, for example, for maintenance). The
documentation would just be silently generated and you would have no
idea about the time bomb in your code that's just waiting for someone to
do something wrong.

That being said, though, I think you have a little of a point. It would
make sense to be able to have the compiler infer the throws clause for
certain methods, such as private (perhaps even package protection)
methods in a class. Adding such a thing would certainly encourage more
decomposition of methods, which is a good thing. I'm afraid, though,
that you're proposing that we throw the baby out with the bathwater;
removing checked exceptions for public or protected methods on classes
that are used from outside of their package would be missing out on a
significant advantage of the language.
Post by James Harris
Type safety is valid but the analogy can be taken too far.
Do you have any basis for this? Lots of people have different tastes
with regard to how much static validation should be performed on code;
but you should at least recognize that you're drawing the line rather
arbitrarily. Have you substantially used languages with much stronger
type systems (say, ML or Haskell)? Do you propose any specific criteria
for making the decision as to whether certain static validation features
are beneficial or not?
Post by James Harris
Sure, this ties the language down more but is an unnecessary
restriction.
All static validation such as type checking is, by definition,
unnecessary restriction. It is included anyway because it is often
helpful, even if not necessary.
Post by James Harris
Post by James Harris
In terms of code maintenance, if dd could once throw a given
exception but now, because the relevant code has been removed, it
cannot does cc still need to provide for handling the exception
simply /because/ it is listed in dd's throws clause?
Yes.
This seems a good case in point of why Java's approach is wrong. Maybe
there is a better way.
Here again, I'd suggest you take the time to look at the throws clause
from a contract standpoint. If code maintenance removed the possibility
of an error at some point, it seems equally likely that further
maintenance would add it back again. It would, in that case, seem like
a very good idea to continue handling potential problems in the code.
On the other hand, if there's some specific reason why it's to be
expected that a certain error will not occur, then you can express that
by removing the exception from the throws clause.
--
Chris Smith
Lew
2007-02-19 02:45:11 UTC
Permalink
Post by Chris Smith
To understand this bit of language design, you need to get your head
around the fact that declaring methods isn't some boilerplate thing that
you do because the compiler makes you. A method declaration is a
contract with a caller, and the fact that certain errors can be
generated is part of that contract. ...
Java is one of the languages for those times when static checking and other
"big iron" scaffolding are the order of the day. It is well suited to
"development by contract", a possible term for the methodology Chris described
so eloquently.

It is natural that Java feels a little stuffy at times, but the formality
serves the goals of system robustness, correctness, adaptability and
longevity. I think of Java as "industrial strength", "big bore", perhaps
"armored". These are good things, especially given that Java accomplishes
these things with, all things considered, a reasonably "light" language flavor
overall.

Chris showed how a certain thought process is compatible with what Java offers
for exception declaration semantics. Use these arguably ponderous idioms for
their intended value and you may come to appreciate their solidity.

- Lew
Robbert Haarman
2007-02-19 23:02:45 UTC
Permalink
Post by Lew
It is natural that Java feels a little stuffy at times, but the formality
serves the goals of system robustness, correctness, adaptability and
longevity.
The problem is that Java falls short on multiple counts here, the way I
see it. You get robustness up to unchecked exceptions and casts. You get
correctness as far as Java's type system can express it. I don't agree
with the adaptability at all; if I had to name one language which
encourages "design first, implement later, and don't even think about
changing the design", Java would be it. As for longevity, I have seen
several programs compiled for older versions break on newer versions, so
I cannot really support that either. However, Java was young at the time
I made these observations; it might have matured and stabilized in the
meantime.

Regardless of Java not scoring perfectly with respect to the qualities
you mentioned, it may still be that Java strikes a very good balance
between them. However, I feel that the balance Java strikes is not the
right one for every purpose. In fact, I am convinced that no one balance
would be perfect for all situations. That is why I think Java's real
weakness is not the balance it strikes, but the extent to which that
balance is cast in stone.

In particular, if you want the commonly useful behavior that any
exception should propagate up the call chain until it is handled, and if
it is not handled otherwise, the program should abort with an error
message, you still have to write "throws Exception" and a try ... catch
block (or, alternatively, convert checked exceptions to unchecked
exceptions at some point).

Regards,

Bob
--
Wise men talk because they have something to say; fools, because they
have to say something.

-- Plato
Lew
2007-02-19 23:54:35 UTC
Permalink
Post by Robbert Haarman
In particular, if you want the commonly useful behavior that any
exception should propagate up the call chain until it is handled, and if
it is not handled otherwise, the program should abort with an error
message, you still have to write "throws Exception" and a try ... catch
block (or, alternatively, convert checked exceptions to unchecked
exceptions at some point).
Not true. If you want to throw an exception that behaves as you describe,
simply throw an unchecked exception and handle it farther up the chain, just
as you say you want. No "mandatory throws clause" needed.

Of course, then you sacrifice the benefits of checked exceptions, but that is
your absolute right as a designer.

If someone else wrote a method with a checked exception that you want to use,
then that programmer is the one requiring you to handle the exception, not
Java, the language itself. That means that that programmer thought about their
API and decided that the exception was important enough to warrant mandatory
handling on the part of all the API's consumers.

Don't blame the language for the programmer's decision. They could have used
an unchecked exception but chose instead to declare a checked one. That is the
power of choice that Java gave them.

- Lew
Robbert Haarman
2007-02-20 00:19:57 UTC
Permalink
Post by Lew
Post by Robbert Haarman
In particular, if you want the commonly useful behavior that any
exception should propagate up the call chain until it is handled, and if
it is not handled otherwise, the program should abort with an error
message, you still have to write "throws Exception" and a try ... catch
block (or, alternatively, convert checked exceptions to unchecked
exceptions at some point).
Not true. If you want to throw an exception that behaves as you describe,
simply throw an unchecked exception and handle it farther up the chain,
just as you say you want. No "mandatory throws clause" needed.
Yes, of course. If you write the code, you can write whatever you want,
including code that never throws any exceptions at all. However, that is
not the situation I was referring to. I meant the case where you use an
existing method which could throw an exception.

For example, and I apologize in advance if I don't get the details
exactly right, if you were to write a program that read a file and wrote
its contents to standard output, you could write the following:

public void passThroughStream(InputStream is, OutputStream os) {
// some code to read from the input stream and write to
// the output stream, which could throw IOException
}

public void passThroughFile(String name, OutputStream os) {
// open the file and call passThroughStream
}

public static void main(String args[]) {
passThroughFile(args[0], System.out);
}

However, this code would not work, because the IOException is not
handled. If you want the exception to propagate up the call chain and
eventually abort the program with an error message, you would need to
add throws clauses to both passThrough* methods, and a try ... catch
block to main, or convert the IOException to an unchecked exception;
precisely as I said.

Regards,

Bob
--
I can't be wrong -- my modem is error-correcting.
Lew
2007-02-20 00:46:25 UTC
Permalink
Post by Robbert Haarman
Yes, of course. If you write the code, you can write whatever you want,
including code that never throws any exceptions at all. However, that is
not the situation I was referring to. I meant the case where you use an
existing method which could throw an exception.
For example, and I apologize in advance if I don't get the details
public void passThroughStream(InputStream is, OutputStream os) {
// some code to read from the input stream and write to
// the output stream, which could throw IOException
}
public void passThroughFile(String name, OutputStream os) {
// open the file and call passThroughStream
}
public static void main(String args[]) {
passThroughFile(args[0], System.out);
}
However, this code would not work, because the IOException is not
handled. If you want the exception to propagate up the call chain and
eventually abort the program with an error message, you would need to
add throws clauses to both passThrough* methods, and a try ... catch
block to main, or convert the IOException to an unchecked exception;
precisely as I said.
But this is not a Java issue, it is a design issue with the method that
declares that it throws the IOException. That is something that the designer
of that method put in for a reason. Mainly, it alerts you at compile time that
you have handled those things in the method that can be handled, or not.

That is a good thing, for that method with that particular exception. It is
the API designer's way of helping you. It says nothing about whether checked
exceptions /per se/ are a good thing, unless you agree with me that this
particular use actually helps the user of the API and that therefore the fact
that Java allowed the API designer to do it is also a good thing.

Discussion of whether checked exceptions are a "good" or "bad" feature of Java
does not depend on how one specific API call uses the feature, but on whether
the feature helps programmers and fails to hinder them.

As to whether a particular checked exception is "good" or "bad" for, say, a
Reader.read() call, that is a different matter. I think that the declaration
in the throws clause really helps the API consumer to be thorough in handling
what can go wrong.

In any event, just because one particular method uses a throws clause doesn't
make the throws clause itself mandatory in the language. It is a feature that
some programmer chose to use, just like you can when it's your API to write.

- Lew
Chris Uppal
2007-02-19 13:46:42 UTC
Permalink
Post by Chris Smith
To understand this bit of language design, you need to get your head
around the fact that declaring methods isn't some boilerplate thing that
you do because the compiler makes you. A method declaration is a
contract with a caller, and the fact that certain errors can be
generated is part of that contract.
But you haven't demonstrated that including a promise of the form "The method
must throw no exceptions except X, Y and Z" is actually adding value to the
contract. I agree that Java /does/ require you to include a clause of that
form in every single method's contract -- the question is whether that's a good
way to write method contracts in general.

-- chris
Chris Smith
2007-02-19 16:20:16 UTC
Permalink
Post by Chris Uppal
But you haven't demonstrated that including a promise of the form "The method
must throw no exceptions except X, Y and Z" is actually adding value to the
contract.
Indeed, I haven't.

As a step in that direction, I would point out that if one intends to
handle error conditions, then the kinds of error conditions that may
arise IS part of the contract between caller and callee. There should
be no discussion of whether it ought to be, or ought not to be. There
is no other choice; the caller needs to handle those error conditions,
and therefore will have knowledge about what conditions they can be. So
the real questions are: Should that knowledge be statically validated
or should it be the job of human developers to convince themselves that
they've handled all possibilities? If statically validated, is there a
better way of propogating the knowledge so as not to affect intermediate
carriers?

As for the first question, it is not at all clear to me how anyone could
answer it in a general way. Obviously, there are some kinds of problems
for which static validation doesn't carry its weight in syntax and
wordiness, which is why Java has some unchecked exceptions. It is
equally clear to me that there are situations in which it does. IMO,
the important issue is where the line is drawn; and if the line is drawn
too close to one edge -- that "nearly all" or "nearly no" errors should
be statically validated in this way -- whether it's a desirable
simplification to make a universal decision despite knowing that it is
occasionally useful to decide the other way.

I don't have answers to those dillemas. Ultimately they can only be
answered empirically and socially. They are not technical questions. I
argued the other side because, in James' post that I replied to, the
treatment of arguments in favor of static validation was unnecessarily
shallow, and I got the idea that those arguments were not properly
explained. (But I didn't see the thread up to this point, so I could be
wrong.)

As for the second question, I think the answer is yes; there are ways to
improve propogation of error conditions. It ought to be possible for a
function to act as a "carrier" for errors that it does not itself know
about. This is actually a major barrier to numerous styles of code in
Java; but it is solvable without entirely rejecting any static
validation that errors are handled.
--
Chris Smith
Chris Uppal
2007-02-19 20:45:08 UTC
Permalink
Post by Chris Smith
As a step in that direction, I would point out that if one intends to
handle error conditions, then the kinds of error conditions that may
arise IS part of the contract between caller and callee.
I agree that there is a contract there (or damn well should be one ;-) But I
don't think it's between the caller and callee -- it seems to me that the
contact (formal or informal) is between the operation, and the handler for any
errors. Java insists on treating every method call as if the caller and callee
were the two principles in that relationship -- and they aren't necessarily,
which is what causes these difficulties.
Post by Chris Smith
So
the real questions are: Should that knowledge be statically validated
or should it be the job of human developers to convince themselves that
they've handled all possibilities? If statically validated, is there a
better way of propogating the knowledge so as not to affect intermediate
carriers?
As for the first question, it is not at all clear to me how anyone could
answer it in a general way. Obviously, there are some kinds of problems
for which static validation doesn't carry its weight in syntax and
wordiness, which is why Java has some unchecked exceptions. It is
equally clear to me that there are situations in which it does.
Agreed. In a sense the cases where one /doesn't/ feel the need for static
validation are uninteresting (just don't validate ;-). It's the cases where we
do want validation, but not necessarily as Java provides it, that are
interesting (to me, anyway).

My own suggestion in this area (you'll have to check Google if you're
interested) was a very pragmatic (read: "very hacky") half-way house, in which
the user of an object has some small choice in /what/ contract is statically
enforced. I can't think of anything significantly better in any of the
dimensions of safety, formal soundness, or convenience, which doesn't involve
(potentially) whole-program analysis (which I loath), or load-time/run-time
checks (which I'm quite happy with, but are not every Java programmer's cup of
tea).
Post by Chris Smith
As for the second question, I think the answer is yes; there are ways to
improve propogation of error conditions. It ought to be possible for a
function to act as a "carrier" for errors that it does not itself know
about. This is actually a major barrier to numerous styles of code in
Java; but it is solvable without entirely rejecting any static
validation that errors are handled.
<Nods/>

-- chris
Chris Smith
2007-02-20 05:55:02 UTC
Permalink
Post by Chris Uppal
Post by Chris Smith
As a step in that direction, I would point out that if one intends to
handle error conditions, then the kinds of error conditions that may
arise IS part of the contract between caller and callee.
I agree that there is a contract there (or damn well should be one ;-) But I
don't think it's between the caller and callee -- it seems to me that the
contact (formal or informal) is between the operation, and the handler for any
errors. Java insists on treating every method call as if the caller and callee
were the two principles in that relationship -- and they aren't necessarily,
which is what causes these difficulties.
I'll stick with the original statement. All contracts are between the
caller and the callee. For example, in Arthur O'Dwyer's example, there
is certainly a contract between 'catcher' and 'higherLevel' -- namely,
that 'higherLevel' will throw only those checked exceptions that may be
thrown by the function being passed as its first argument. It would not
be acceptable for 'higherLevel' to throw an IOException on the side, for
example, if that's not expected by 'catcher'.

I'm having trouble assigning meaning to the statement that there's a
contract between a function and the code that handles its errors. The
whole point is to try to use the contract to guarantee that, in fact,
the error handler exists. The error handler can't be a party to such a
contract unless you guarantee that it exists in some other way.
Post by Chris Uppal
My own suggestion in this area (you'll have to check Google if you're
interested) was a very pragmatic (read: "very hacky") half-way house, in which
the user of an object has some small choice in /what/ contract is statically
enforced.
I'm afraid my Google-zen is failing me on that one. I can sort of
imagine what you may be thinking, though. I agree that a general
solution will need to be flexible and allow people to make these
decisions on a case-by-case basis; that is, there is no magical answer
that will satisfy all needs. I assume that by giving choice to the
"user", you intend to avoid situations like on one hand the
NumberFormatException dilemma, and on the other hand the close() throws
IOException issue; where it seems obvious in retrospect that the wrong
decisions were made, but the choices about strictness of enforcement are
enshrined in library design?
--
Chris Smith
Chris Uppal
2007-02-20 20:05:48 UTC
Permalink
Post by Chris Smith
I'm having trouble assigning meaning to the statement that there's a
contract between a function and the code that handles its errors. The
whole point is to try to use the contract to guarantee that, in fact,
the error handler exists. The error handler can't be a party to such a
contract unless you guarantee that it exists in some other way.
By the error handler I mean the code who's job it is to detect, and correct,
log, or otherwise deal with, any thrown exceptions (Throwables). In java that
must be a catch clause (or a Thread.UncaughtExceptionHandler if we want to be
pedanticn ;-). By the "operation" I mean the code which originally detects the
underlying error condition and signals it by throwing a Throwable.

Take this case (different from the running examples elsethread only for
variety).

outer()
{
try
{
aaa();
}
catch (MyException e)
{
// whatever
}
}

aaa() { bbb(); }
bbb() { inner(); }

inner()
throws MyException
{
// whatever
}

I contend that the contract is between the code in outer() and the code in
inner(), and that neither aaa() nor bbb() should be forced to be party to that
contract (although they often will be anyway).
Post by Chris Smith
Post by Chris Uppal
I agree that there is a contract there (or damn well should be one ;-)
But I don't think it's between the caller and callee -- it seems to me
that the contact (formal or informal) is between the operation, and the
handler for any errors. Java insists on treating every method call as
if the caller and callee were the two principles in that relationship
-- and they aren't necessarily, which is what causes these difficulties.
I'll stick with the original statement. All contracts are between the
caller and the callee.
Maybe it's just a difference in terminology. I meant the /immediate/ caller
and callee in that paragraph. If you want to call outer() and inner() the
caller and callee, then I'd agree that the contract is between caller and
callee -- but I want to use those words more narrowly.
Post by Chris Smith
Post by Chris Uppal
My own suggestion in this area (you'll have to check Google if you're
interested) was a very pragmatic (read: "very hacky") half-way house,
in which the user of an object has some small choice in /what/ contract
is statically enforced.
I'm afraid my Google-zen is failing me on that one. I can sort of
imagine what you may be thinking, though.
Sorry:


<http://groups.google.co.uk/group/comp.lang.java.programmer/browse_frm/thread/c
2eeada2c54a3e54/850df1ddd50c6856>

Probably less general or flexible than you were imagining. Essentially the
idea is to change the meaning of a throws clause from "I will throw nothing but
X, Y, Z" to "I have the right to throw X, Y, Z".
Post by Chris Smith
I agree that a general
solution will need to be flexible and allow people to make these
decisions on a case-by-case basis; that is, there is no magical answer
that will satisfy all needs. I assume that by giving choice to the
"user", you intend to avoid situations like on one hand the
NumberFormatException dilemma, and on the other hand the close() throws
IOException issue; where it seems obvious in retrospect that the wrong
decisions were made, but the choices about strictness of enforcement are
enshrined in library design?
I don't think it's possible in general to fix problems caused by poor library
design. The best we can even aim for is that the language doesn't make /good/
library design harder than it has to be.

-- chris
Chris Smith
2007-02-21 15:22:12 UTC
Permalink
Post by Chris Uppal
Take this case (different from the running examples elsethread only for
variety).
Actually, it is significantly different in very important ways from the
example with the callback function declared elsewhere.
Post by Chris Uppal
outer()
{
try
{
aaa();
}
catch (MyException e)
{
// whatever
}
}
aaa() { bbb(); }
bbb() { inner(); }
inner()
throws MyException
{
// whatever
}
I contend that the contract is between the code in outer() and the code in
inner(), and that neither aaa() nor bbb() should be forced to be party to that
contract (although they often will be anyway).
I definitely disagree with this. It breaks abstractions. Since outer
doesn't know that it ever interacts with inner, it cannot possibly be
under any kind of contractual relationship with inner. The only piece
of code with which outer has any relatinship is aaa (and the code which
calls it, which is insignificant here). Therefore, if there is any hope
of providing the static validation at all while respecting abstraction,
there needs to be something about aaa to indicate that it can fail in
those ways.

It's also not clear how you define outer as the method that has the
contract with inner. Is it that outer contains the catch block? If I
remove that contract, would you deny that outer should be forced to be
party to the contract? Then we're back to the original problem; if no
one has a catch block, then who is the other party to the contract?

I agree that it would be nice if the throws clause for aaa and bbb could
be inferred in some cases, esp. if they are private methods. I would
insist that the contractual obligations between caller and callee still
exist; it's just that you don't have to explicitly declare them.
Post by Chris Uppal
Post by Chris Smith
I'll stick with the original statement. All contracts are between the
caller and the callee.
Maybe it's just a difference in terminology.
Nope, clearly not.
--
Chris Smith
Chris Uppal
2007-02-21 16:28:59 UTC
Permalink
Chris Smith wrote:

[me:]
Post by Chris Smith
Post by Chris Uppal
Take this case (different from the running examples elsethread only for
variety).
Actually, it is significantly different in very important ways from the
example with the callback function declared elsewhere.
Post by Chris Uppal
outer()
{
try
{
aaa();
}
catch (MyException e)
{
// whatever
}
}
aaa() { bbb(); }
bbb() { inner(); }
inner()
throws MyException
{
// whatever
}
I contend that the contract is between the code in outer() and the code
in inner(), and that neither aaa() nor bbb() should be forced to be
party to that contract (although they often will be anyway).
I definitely disagree with this. It breaks abstractions. Since outer
doesn't know that it ever interacts with inner, it cannot possibly be
under any kind of contractual relationship with inner. The only piece
of code with which outer has any relatinship is aaa (and the code which
calls it, which is insignificant here). Therefore, if there is any hope
of providing the static validation at all while respecting abstraction,
there needs to be something about aaa to indicate that it can fail in
those ways.
Contrariwise, there is no reason why bbb() should expose its relationship with
inner() -- that is also breaking abstraction. Even more so for aaa(). In fact
it is complicating the relationship between aaa() and bbb() by introducing
irrelevant (to them) complications and conditions on how they fit together.
Post by Chris Smith
It's also not clear how you define outer as the method that has the
contract with inner. Is it that outer contains the catch block? If I
remove that contract, would you deny that outer should be forced to be
party to the contract? Then we're back to the original problem; if no
one has a catch block, then who is the other party to the contract?
I think we are still differing in terminology -- this time about "contract".
For me it is about assigning a certain responsibility, and (perhaps) policing
whether that responsibility is met. Specifically, it's an architectural thing:
the Achitect has deemed that <this place in the code> shall be responsible for
handling errors (etc) detected in <these places in the code>. (Or you could
even say it's an organisational thing, and replace <place in the code> with
<programmer> -- it doesn't make all that much different from my point of view).
So there are two questions to answer. (1) are notifications of errors (etc)
channeled to the righjt place ? Java has the tools to handle that very nicely.
(2) Are all the errors which are supposed to reach <the right place> actually
handled there ? Ideally we'd like to be able to police this automatically.

But we can't do that without accepting one or another of several rather
unappealing options: we can increase coupling and reduce flexibility by
requiring that every method "carry-forward" the contract of everything it
touches; or we can require whole program analysis; or we can weaken the
checking to the point where it doesn't cover everthing we'd like it to.

(As an aside, you may remember that I'm no big fan of static analysis and
checking -- this is one of the cases where I feel much more positive about it,
specifically /because/ the relationship between the parties is non-local --
unlike parameter types, say.)

-- chris
Chris Smith
2007-02-21 19:36:08 UTC
Permalink
Post by Chris Uppal
Contrariwise, there is no reason why bbb() should expose its relationship with
inner() -- that is also breaking abstraction.
If bbb were exposing its relationship with inner, then that would be
breaking abstraction. That's not what's going on, though. bbb is
making the (true) statement that it can fail in certain ways. Whether
it can fail that way because it calls inner or for some other reason, is
immaterial and is properly hidden behind an abstraction boundary.

It seems to me you're proposing we break that boundary. What would
strike me as odd is if bbb needed a different publicly visible
declaration depending on whether it throws IOException by using a
FileInputStream directly, or by calling inner to do the same thing.
That is not a choice that affects anyone except bbb.

Another way of putting the same thing: if it's too hard to construct and
throw some complex exception directly, I ought to be able to say

private void throwException(ComplexData d) throws ComplexException
{
...
}

then I could reasonably expect that the line:

public void foo()
{
...
throwException(myComplexData);
...
}

would be approximately equivalent to a throw statement. Specifically,
it should fail validation. But it seems that you're saying that it
should be fine, because it's just acting as a carrier for that exception
and shouldn't need to know about it. Yet that's not really true. In
every way, my foo absolutely knows that it may throw that exception, and
it should know. I just made the irrelevant implementation choice to
encapsulate some complex block of code into a separate method. I don't
want my static validation to break as a result.
Post by Chris Uppal
In fact it is complicating the relationship between aaa() and bbb() by
introducing irrelevant (to them) complications and conditions on how
they fit together.
How is it irrelevant? It's only irrelevant if there's some other way
for outer to know that it's indirectly calling inner or otherwise
incurring those error conditions. But ANY other way for that knowledge
to exist besides via aaa is necessarily violating the abstraction
boundaries defined by aaa. That is necessary because I can make that
piece of knowledge false simply by changing the implementation of aaa;
and changing the implementation of aaa is right at the core of what
abstraction is supposed to protect me from.
Post by Chris Uppal
I think we are still differing in terminology -- this time about "contract".
For me it is about assigning a certain responsibility, and (perhaps) policing
the Achitect has deemed that <this place in the code> shall be responsible for
handling errors (etc) detected in <these places in the code>.
What if the "Architect" has forgotten to do so?
Post by Chris Uppal
But we can't do that without accepting one or another of several rather
unappealing options: we can increase coupling and reduce flexibility by
requiring that every method "carry-forward" the contract of everything it
touches;
This isn't nearly so unreasonable as you make it sound. The fact is
that aaa CAN fail in those ways. Your choices are to declare it, or (in
some other language) to not declare it. The only arguments I see for
not declaring it are:

1. The Java language features are not sufficient to capture everything
you want here; e.g., the callback example elsewhere.

2. It's too much typing.

I don't see anything else that's valid. How could this possibly
increase coupling? The coupling is there whether you choose to ignore
it or not. Flexibility? The obligation exists to handle that error
whenever you call aaa, whether or not you declare it. These attributes
are all common to the validated and non-validated situations; it's just
that in one case, someone holds it all in their head.
--
Chris Smith
Arne Vajhøj
2007-02-19 02:18:03 UTC
Permalink
Post by James Harris
One valid argument for Java's enforcing is that it documents part of
the subprogram's interface. Isn't this, however, ultimately incomplete
as Errors can occur which are undeclared?
Not really.

Exceptions are intended to be used for something the
program can handle.

Errors are intended to be used for something the
program can not handle.
Post by James Harris
My main objections to Java's way is that if aa calls bb calls cc ...
calls zz and I want to handle zz's errors in aa I still have to either
declare them in all intervening modules or catch a generic Exception
superclass and possibly encapsulate them in another object. The latter
is a kludge, IMHO. The former unfortunately obscures the program logic
and intention with foreign constructs or "mechanism."
I find it very hard to see how it obscures the code to express
its behavior.
Post by James Harris
It doesn't seem unreasonable to accept that a given subprogram can
generate arbitrary errors.
If that is what you like, then do it.

That programming model is supported by Java. Just let all
your exception extend RuntimeException instead of Exception.
Post by James Harris
Post by Tor Iver Wilhelmsen
Yes. In the same way there is value in the type safety of a strongly
typed language over an untyped one, for instance.
Type safety is valid but the analogy can be taken too far. For
example, Pascal regards the dimensions of an array as part of the
type. Sure, this ties the language down more but is an unnecessary
restriction.
Depends on the level of robustness you need. If an
IndexOutOfBoundsException will cost human lifes, then
maybe a language that does this type of checking
compile time is a good thing.

(today Ada is probably the most widely used language
that really checks that kind of stuff)

Arne
Robbert Haarman
2007-02-19 22:25:49 UTC
Permalink
Post by Arne Vajhøj
Post by James Harris
One valid argument for Java's enforcing is that it documents part of
the subprogram's interface. Isn't this, however, ultimately incomplete
as Errors can occur which are undeclared?
Not really.
Exceptions are intended to be used for something the
program can handle.
Errors are intended to be used for something the
program can not handle.
This gets to the heart of what I think really is wrong with Java's
exceptions (and, in a wider sense, the whole language). I would say the
exceptions that can or cannot be usefully handled depend on the specific
case. Yet, the list of exceptions that your program must handle (as well
as the list of exceptions it does not have to handle explicitly) has
been hardcoded into the language by the designers, in their wisdom.

I am sure that having the compiler check that certain conditions are
accounted for is a good idea. I am not so sure that hardcoding the
(essentially arbitrary) list of exceptions the compiler will do this
for, and forcing that list on every program, is a good idea.
Post by Arne Vajhøj
Post by James Harris
My main objections to Java's way is that if aa calls bb calls cc ...
calls zz and I want to handle zz's errors in aa I still have to either
declare them in all intervening modules or catch a generic Exception
superclass and possibly encapsulate them in another object. The latter
is a kludge, IMHO. The former unfortunately obscures the program logic
and intention with foreign constructs or "mechanism."
I find it very hard to see how it obscures the code to express
its behavior.
Certainly, adding code that deals with exceptional situations to the
code that carries out the normal operations obscures those operations.
This is excactly why exceptions are such a good idea: you can have error
checking and handling, without having to litter your code with checks
and error handling code. The more salt the language forces you to add
(which includes not just throws clauses, but also type annotations,
casts, ...), the less clear the function of a snippet of code becomes.
You can argue that you get something in return, but I don't think you
can argue that the function of the code is not obscured.
Post by Arne Vajhøj
Post by James Harris
It doesn't seem unreasonable to accept that a given subprogram can
generate arbitrary errors.
If that is what you like, then do it.
That programming model is supported by Java. Just let all
your exception extend RuntimeException instead of Exception.
The problem is that neither Java, nor many of its adherents will let you
get away with that. Java won't, because many exceptions are already hard
coded to be checked exceptions. It's adherents won't, because they
consider unchecked exceptions bad style. And they have a point: it's not
the Java Way, and thus, if you are programming in Java, it is not what
you should do.

Regards,

Bob
--
Coal powered the first steam engines, whose killer app was pumping
stagnant water out of coal mines. It powered the railroads, whose killer
app was moving coal.

-- Bruce Sterling
Lew
2007-02-20 00:06:41 UTC
Permalink
Post by Robbert Haarman
This gets to the heart of what I think really is wrong with Java's
exceptions (and, in a wider sense, the whole language). I would say the
exceptions that can or cannot be usefully handled depend on the specific
case. Yet, the list of exceptions that your program must handle (as well
as the list of exceptions it does not have to handle explicitly) has
been hardcoded into the language by the designers, in their wisdom.
I am sure that having the compiler check that certain conditions are
accounted for is a good idea. I am not so sure that hardcoding the
(essentially arbitrary) list of exceptions the compiler will do this
for, and forcing that list on every program, is a good idea.
You have an interesting idea of "hard coded". The Exceptions that Java
provides are by no means exhaustive, nor mandatory. You can derive your own,
or choose not to use any of the library Exceptions, just like you are not
required to use any other part of the APIs.

Do you object to the presence of the substring() method in java.lang.String
just because you don't always use it?

It is the nature of APIs, especially ones as robust and comprehensive as the
ones Java offers, to have more than you need, but there are no "API police"
running around forcing you as a programmer to use this method or that Exception.

It is the nature of an API to provide more than any one programmer or project
needs at a time, if it is a good API. Complaining that an API provides things
you personally don't need is actually complaining about a strength of the API.

What you characterize as something "wrong" with Java is simply a choice that
one need not make in Java at all. When someone does choose to use that part of
the API, then clearly that programmer found value in it and is thanking Sun
for having provided it.

- Lew
Robbert Haarman
2007-02-20 00:43:01 UTC
Permalink
Post by Lew
You have an interesting idea of "hard coded".
I simply meant that every exception derived from one class (I think
Exception) is a checked exception, and every exception derived from
another class (I think Error) is an unchecked exception. There is
(AFAIK) no way to influence the compiler's behavior after the decision
about which class to derive the exception from has been taken.

Such a way would be useful. For example, to write more robust code, it
could be useful to be able to tell the compiler that a certain program
or snippet of code must catch all exceptions, no matter their base
class.
Post by Lew
What you characterize as something "wrong" with Java is simply a choice
that one need not make in Java at all. When someone does choose to use that
part of the API, then clearly that programmer found value in it and is
thanking Sun for having provided it.
Thanking Sun for providing something is different from saying it is
perfect.

Regards,

Bob
--
May the source be with you!
Arne Vajhøj
2007-02-20 01:21:38 UTC
Permalink
Post by Robbert Haarman
I simply meant that every exception derived from one class (I think
Exception) is a checked exception, and every exception derived from
another class (I think Error) is an unchecked exception.
RuntimeException.

Error are a third category. But less relevant since your code should not
throw errors or handle errors.
Post by Robbert Haarman
There is
(AFAIK) no way to influence the compiler's behavior after the decision
about which class to derive the exception from has been taken.
They needed to mark the difference in some way. Annotations were
not invented in Java 1.0.
Post by Robbert Haarman
Such a way would be useful. For example, to write more robust code, it
could be useful to be able to tell the compiler that a certain program
or snippet of code must catch all exceptions, no matter their base
class.
I do not think that will work well with the Java compile model. Some
of the code may have been compiled by someone else.

Arne
Bent C Dalager
2007-02-20 10:32:40 UTC
Permalink
Post by Robbert Haarman
Such a way would be useful. For example, to write more robust code, it
could be useful to be able to tell the compiler that a certain program
or snippet of code must catch all exceptions, no matter their base
class.
This would seem to make the program less robust in many interesting
cases. For example, let us say that you have written a program that
uses a number of interfaces to access interesting functionality. When
the time comes to deploy the program, it turns out that on some
platforms it refuses to run because the interface implementations on
those platforms happen to use arrays and your compiler never
considered that the methods in question might throw
ArrayIndexOutOfBoundsException because the implementations you worked
with didn't use arrays at all. You therefore never wrote a catch
clause for those exceptions (since your compiler didn't require you to
and you didn't think to do it) and so your program is invalid in this
particular setting.

It would also be somewhat tedious to _have_ to handle the possibility
of a NullPointerException on almost every single line of source code.

Cheers
Bent D
--
Bent Dalager - ***@pvv.org - http://www.pvv.org/~bcd
powered by emacs
Robbert Haarman
2007-02-20 11:35:55 UTC
Permalink
Post by Bent C Dalager
Post by Robbert Haarman
Such a way would be useful. For example, to write more robust code, it
could be useful to be able to tell the compiler that a certain program
or snippet of code must catch all exceptions, no matter their base
class.
This would seem to make the program less robust in many interesting
cases. For example, let us say that you have written a program that
uses a number of interfaces to access interesting functionality. When
the time comes to deploy the program, it turns out that on some
platforms it refuses to run because the interface implementations on
those platforms happen to use arrays and your compiler never
considered that the methods in question might throw
ArrayIndexOutOfBoundsException because the implementations you worked
with didn't use arrays at all. You therefore never wrote a catch
clause for those exceptions (since your compiler didn't require you to
and you didn't think to do it) and so your program is invalid in this
particular setting.
It depends on your meaning of "robust". What I had in mind was ensuring
the program is robust (at run time) by rejecting it, unless all possible
run time conditions are taken care of. Thus, rejecting the program based
on unhandled ArrayIndexOutOfBoundsExceptions is a feature, and makes any
program that still passes compilation _more_ robust.
Post by Bent C Dalager
It would also be somewhat tedious to _have_ to handle the possibility
of a NullPointerException on almost every single line of source code.
Nothing requires you to put catch blocks around _every_ line of code.

Regards,

Bob
--
The early bird gets the worm, but the second mouse gets the cheese.
Bent C Dalager
2007-02-20 13:59:32 UTC
Permalink
Post by Robbert Haarman
Post by Bent C Dalager
Post by Robbert Haarman
Such a way would be useful. For example, to write more robust code, it
could be useful to be able to tell the compiler that a certain program
or snippet of code must catch all exceptions, no matter their base
class.
It would also be somewhat tedious to _have_ to handle the possibility
of a NullPointerException on almost every single line of source code.
Nothing requires you to put catch blocks around _every_ line of code.
Where would you require the catch blocks to be in order to consider
the exception handled?

Cheers
Bent D
--
Bent Dalager - ***@pvv.org - http://www.pvv.org/~bcd
powered by emacs
Robbert Haarman
2007-02-20 14:31:39 UTC
Permalink
Post by Bent C Dalager
Post by Robbert Haarman
Nothing requires you to put catch blocks around _every_ line of code.
Where would you require the catch blocks to be in order to consider
the exception handled?
Anywhere that causes the exception to be caught by the program. In other
words, exceptions that must be handled are only allowed to be throwable
inside the dynamic scope of a catch block that handles them. E.g., if
IOException is such an exception, writing

try {
line = inFile.readLine();
} catch(IOException ioe) {
// do something
}

try {
outFile.write(line);
} catch(IOException ioe) {
// do something
}

handles the exception, as does (pseudocode)

passThroughLine(inFile, outFile) {
outFile.write(inFile.readLine());
}

passThroughLines(inFile, outFile) {
while(!inFile.eof()) {
passThroughLine(inFile, outFile);
}
}

try {
passThroughLines(inFile, outFile);
} catch(IOException ioe) {
// do something
}

Regards,

Bob
--
Only after the last tree has
been cut down

Only after the last river has
been poisoned

Only after the last fish has
been caught

Only then will you find that
money cannot be eaten.

(Cree Indian Prophecy)
Arne Vajhøj
2007-02-20 01:18:29 UTC
Permalink
Post by Robbert Haarman
Post by Arne Vajhøj
Exceptions are intended to be used for something the
program can handle.
Errors are intended to be used for something the
program can not handle.
This gets to the heart of what I think really is wrong with Java's
exceptions (and, in a wider sense, the whole language). I would say the
exceptions that can or cannot be usefully handled depend on the specific
case.
What can the code do in case of a OutOfMemoryError ?

Errors are intended for the not able to be handled in any case.
Post by Robbert Haarman
Yet, the list of exceptions that your program must handle (as well
as the list of exceptions it does not have to handle explicitly) has
been hardcoded into the language by the designers, in their wisdom.
Not at all. Everyone can and should create their own exceptions.
Post by Robbert Haarman
I am sure that having the compiler check that certain conditions are
accounted for is a good idea. I am not so sure that hardcoding the
(essentially arbitrary) list of exceptions the compiler will do this
for, and forcing that list on every program, is a good idea.
The programmer writing a method has the ability to declare the method
with a throws that forces the programmer using the method to do
something to handle it.

If the first programmer does not like it, then he just use unchecked
exceptions.

If the second programmer does mot like it, then he will have to find
a library with an API he likes better.
Post by Robbert Haarman
Post by Arne Vajhøj
If that is what you like, then do it.
That programming model is supported by Java. Just let all
your exception extend RuntimeException instead of Exception.
The problem is that neither Java, nor many of its adherents will let you
get away with that. Java won't, because many exceptions are already hard
coded to be checked exceptions. It's adherents won't, because they
consider unchecked exceptions bad style. And they have a point: it's not
the Java Way, and thus, if you are programming in Java, it is not what
you should do.
SUN developers has been using checked exceptions. But it is rather
universal that if you are using a library, then you must live with
the API provided by those creating the library.

Arne
Robbert Haarman
2007-02-20 10:15:37 UTC
Permalink
Post by Arne Vajhøj
Post by Robbert Haarman
Post by Arne Vajhøj
Exceptions are intended to be used for something the
program can handle.
Errors are intended to be used for something the
program can not handle.
This gets to the heart of what I think really is wrong with Java's
exceptions (and, in a wider sense, the whole language). I would say the
exceptions that can or cannot be usefully handled depend on the specific
case.
What can the code do in case of a OutOfMemoryError ?
It depends, and that is the point I was trying to make. In some cases,
the only thing that can be done is to abort the whole program (and, if
possible, print an error message). In other cases, only the current
operation needs to be aborted, and the rest of the program may be able
to recover from that.
Post by Arne Vajhøj
Errors are intended for the not able to be handled in any case.
And yet I can come up with scenarios in which they can sensibly be
handled.
Post by Arne Vajhøj
Post by Robbert Haarman
Yet, the list of exceptions that your program must handle (as well
as the list of exceptions it does not have to handle explicitly) has
been hardcoded into the language by the designers, in their wisdom.
Not at all. Everyone can and should create their own exceptions.
Since it seems to have confused a number of people, perhaps I did not
word my statement right. What I meant is that, for the exception classes
that have already been defined, and the methods that use them, you
cannot control which ones the compiler requires you to handle
explicitly. Each time a method (defined by someone else) claims it can
throw an IOException, you _must_ handle it explicitly. Never will the
compiler complain if you fail to explicitly handle an OutOfMemoryError.
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
Post by Arne Vajhøj
Post by Robbert Haarman
I am sure that having the compiler check that certain conditions are
accounted for is a good idea. I am not so sure that hardcoding the
(essentially arbitrary) list of exceptions the compiler will do this
for, and forcing that list on every program, is a good idea.
The programmer writing a method has the ability to declare the method
with a throws that forces the programmer using the method to do
something to handle it.
Exactly. And I am asking people to consider whether the first programmer
is in the right position to make that decision.
Post by Arne Vajhøj
If the first programmer does not like it, then he just use unchecked
exceptions.
True. However, I have done this and be criticized for it, because it is
not the canonical way to do things in Java. As said before, you are
expected to use checked exceptions in some cases. If you don't, you
violate people's expectations. Also, you will run into cases where one
of the standarh exception classes would be the right choice. You don't
have any choice about whether that class is checked or unchecked.
Post by Arne Vajhøj
If the second programmer does mot like it, then he will have to find
a library with an API he likes better.
Of course. I've found that API by using a different language than Java.

Regards,

Bob
--
For a list of the ways which technology has failed to improve our
quality of life, press 3.
Lew
2007-02-20 13:16:27 UTC
Permalink
Post by Robbert Haarman
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
That is true for all software written by someone else.

- Lew
Robbert Haarman
2007-02-20 14:24:19 UTC
Permalink
Post by Lew
Post by Robbert Haarman
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
That is true for all software written by someone else.
The language or the compiler could allow you to specify which exceptions
your program must handle explicitly and which ones can be handled
implicitly. This would allow you to make your own trade-off.

Regards,

Bob
--
The surest way to remain a winner is to win once, and then not play any more.
Lew
2007-02-21 03:12:32 UTC
Permalink
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
That is true for all software written by someone else.
The language or the compiler could allow you to specify which exceptions
your program must handle explicitly and which ones can be handled
implicitly. This would allow you to make your own trade-off.
Great idea. We could call the ones that your program must handle explicitly
"checked" exceptions, and the language could signal them by deriving them from
Exception and requiring them in the throws clause of a method signature. The
language could allow implicit exceptions to be handled or trivially rethrown
without a throws clause by deriving them from RuntimeException, and we will
call such cases "unchecked" exceptions.

- Lew
Robbert Haarman
2007-02-21 05:46:38 UTC
Permalink
Post by Lew
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
That is true for all software written by someone else.
The language or the compiler could allow you to specify which exceptions
your program must handle explicitly and which ones can be handled
implicitly. This would allow you to make your own trade-off.
Great idea. We could call the ones that your program must handle explicitly
"checked" exceptions, and the language could signal them by deriving them
from Exception and requiring them in the throws clause of a method
signature. The language could allow implicit exceptions to be handled or
trivially rethrown without a throws clause by deriving them from
RuntimeException, and we will call such cases "unchecked" exceptions.
It seems you have completely missed my point. When you are the one
writing all the code, of course you get to decide which exceptions are
checked exceptions and which aren't, in current Java.

The issue I have been trying to point out is that there is value in
being able to decide this _even when you are not writing all the code_.
For example, that, for this snippet of code, you want OutOfMemoryError
to be a checked exception, and or that for that program, you want
IOException to be an unchecked exception.

Current Java (AFAIK) does not allow you to make that decision.

Regards,

Bob
--
That that is is that that is not not.
Lew
2007-02-21 06:21:13 UTC
Permalink
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
Post by Lew
Post by Robbert Haarman
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
That is true for all software written by someone else.
The language or the compiler could allow you to specify which exceptions
your program must handle explicitly and which ones can be handled
implicitly. This would allow you to make your own trade-off.
Great idea. We could call the ones that your program must handle explicitly
"checked" exceptions, and the language could signal them by deriving them
from Exception and requiring them in the throws clause of a method
signature. The language could allow implicit exceptions to be handled or
trivially rethrown without a throws clause by deriving them from
RuntimeException, and we will call such cases "unchecked" exceptions.
It seems you have completely missed my point. When you are the one
writing all the code, of course you get to decide which exceptions are
checked exceptions and which aren't, in current Java.
The issue I have been trying to point out is that there is value in
being able to decide this _even when you are not writing all the code_.
For example, that, for this snippet of code, you want OutOfMemoryError
to be a checked exception, and or that for that program, you want
IOException to be an unchecked exception.
Current Java (AFAIK) does not allow you to make that decision.
And that is a good thing.

You are saying you want to override another programmer's decision on how their
API should be called. They declare a checked exception and you want to treat
it like an unchecked one. That defeats the whole purpose of them declaring a
checked exception in their API.

Of course, you can always *handle* the exception the other programmer demanded
that you handle. You can always rethrow it as an unchecked exception. But that
is not a flaw in Java. That is you disagreeing with the library writer.

- Lew
Robbert Haarman
2007-02-21 06:47:04 UTC
Permalink
Post by Lew
Post by Robbert Haarman
The issue I have been trying to point out is that there is value in
being able to decide this _even when you are not writing all the code_.
For example, that, for this snippet of code, you want OutOfMemoryError
to be a checked exception, and or that for that program, you want
IOException to be an unchecked exception.
Current Java (AFAIK) does not allow you to make that decision.
And that is a good thing.
You are saying you want to override another programmer's decision on how
their API should be called.
No, I am overriding the decisions about how errors that occur should be
handled in _my_ code.
Post by Lew
They declare a checked exception and you want to treat it like an
unchecked one. That defeats the whole purpose of them declaring a
checked exception in their API.
You are assuming there is such a purpose. I maintain that only I know
whether it makes sense for my code to handle an exception beyond
aborting the thread with an error message. Since we cannot seem to agree
on that, it is pointless to keep arguing the things that depend on it,
so I propose we simply call it a difference in taste and leave it at
that.

Regards,

Bob
--
I can't remember the last time I forgot something.
Chris Uppal
2007-02-21 10:38:29 UTC
Permalink
Post by Lew
Post by Robbert Haarman
The language or the compiler could allow you to specify which exceptions
your program must handle explicitly and which ones can be handled
implicitly. This would allow you to make your own trade-off.
Great idea. We could call the ones that your program must handle
explicitly "checked" exceptions, and the language could signal them by
deriving them from Exception and requiring them in the throws clause of a
method signature. The language could allow implicit exceptions to be
handled or trivially rethrown without a throws clause by deriving them
from RuntimeException, and we will call such cases "unchecked" exceptions.
That's an interesting idea. I think, though, that it has some fairly serious
flaws. You should experiment with it, and with variations, for a while before
baking anything into your language design.

Maybe even try to find another language where it's been tried before, and see
whether it worked there.

;-)


BTW: one problem with the idea, which I've only seen touched on glancingly in
this thread so far, is that /if/ you want to use exception class hierarchies to
express nested categories of exceptional conditions (in itself something of an
abuse of the class concept, albeit useful and natural); then your scheme won't
play properly with that. If an exception hierarchy is to make sense then you
can't use one hierarchy to express two orthogonal concepts. It would be far
better to make the "is checked" a per-class attribute which can be set
independently for each exception class. It might make sense to make "is
checked" be inherited by default (though I'm not convinced[*]), but if so then
subclasses must be able to override the checkedness to turn it on /or/ off.

-- chris

[*] The checkedness of an exception class would be an /extremely/ important
aspect of any design, and I suspect there'd be more value in forcing designers
to make explicit decisions on a per-case basis, than in the (undoubtedly real)
savings in coding effort.
Chris Uppal
2007-02-20 16:48:20 UTC
Permalink
Post by Lew
Post by Robbert Haarman
These are decisions that have been made for you and you cannot change
them, even though, in the program you are writing, different behaviors
may make more sense.
That is true for all software written by someone else.
It isn't unreasonable to expect that the design of any (large-scale) language
will provide the best possible tools for allowing separate (in space, time, or
attitude) programmers to work "together" productively. If the Java approach to
checked exceptions is such that independent programmers (or their work) is more
closely coupled than it could be, then that is a definite downside to Java's
approach to checked exceptions. If that's so then, unless a corresponding
benefit /of that specific approach/ can be found, we should conclude that the
design was a failure and refrain from replicating it in other languages.

-- chris
Arne Vajhøj
2007-02-21 03:17:05 UTC
Permalink
Post by Robbert Haarman
Post by Arne Vajhøj
What can the code do in case of a OutOfMemoryError ?
It depends, and that is the point I was trying to make. In some cases,
the only thing that can be done is to abort the whole program (and, if
possible, print an error message). In other cases, only the current
operation needs to be aborted, and the rest of the program may be able
to recover from that.
Post by Arne Vajhøj
Errors are intended for the not able to be handled in any case.
And yet I can come up with scenarios in which they can sensibly be
handled.
If you have done what noone has been able to in 10 years to
provide a good way of handling OutOfMemoryError then please
post it.
Post by Robbert Haarman
Post by Arne Vajhøj
The programmer writing a method has the ability to declare the method
with a throws that forces the programmer using the method to do
something to handle it.
Exactly. And I am asking people to consider whether the first programmer
is in the right position to make that decision.
I see nobody better to do it.
Post by Robbert Haarman
Post by Arne Vajhøj
If the first programmer does not like it, then he just use unchecked
exceptions.
True. However, I have done this and be criticized for it, because it is
not the canonical way to do things in Java. As said before, you are
expected to use checked exceptions in some cases. If you don't, you
violate people's expectations.
I do not think that is true.

Hibernate 3 switched to unchecked exceptions.

That is a rather well respected Java library.

Arne
Robbert Haarman
2007-02-21 05:53:49 UTC
Permalink
Post by Arne Vajhøj
Post by Robbert Haarman
Post by Arne Vajhøj
What can the code do in case of a OutOfMemoryError ?
It depends, and that is the point I was trying to make. In some cases,
the only thing that can be done is to abort the whole program (and, if
possible, print an error message). In other cases, only the current
operation needs to be aborted, and the rest of the program may be able
to recover from that.
Post by Arne Vajhøj
Errors are intended for the not able to be handled in any case.
And yet I can come up with scenarios in which they can sensibly be
handled.
If you have done what noone has been able to in 10 years to
provide a good way of handling OutOfMemoryError then please
post it.
I wouldn't exactly take credit for this scenario as if I were the only
one to think of it in 10 years, but if you're implementing a cache, if
memory allocation fails, you can simply not cache the item you were
about to cache, or throw out other items to make room for it. The
correctness of the rest of the program should not be affected, only its
performance.
Post by Arne Vajhøj
Post by Robbert Haarman
Post by Arne Vajhøj
The programmer writing a method has the ability to declare the method
with a throws that forces the programmer using the method to do
something to handle it.
Exactly. And I am asking people to consider whether the first programmer
is in the right position to make that decision.
I see nobody better to do it.
How do you know, when implementing a library, whether I will want to
catch and handle a certain error condition? In the example above, I
might want OutOfMemoryError to be a checked exception, because I want to
handle it inside the cache implementation, because, if I don't, it will
abort my program. How do you know if I will use your library code to
implement a cache or not?
Post by Arne Vajhøj
Post by Robbert Haarman
Post by Arne Vajhøj
If the first programmer does not like it, then he just use unchecked
exceptions.
True. However, I have done this and be criticized for it, because it is
not the canonical way to do things in Java. As said before, you are
expected to use checked exceptions in some cases. If you don't, you
violate people's expectations.
I do not think that is true.
Hibernate 3 switched to unchecked exceptions.
That is a rather well respected Java library.
Alright. That's good to hear.

Regards,

Bob
--
"Thou shalt not follow the Null Pointer, for at it's end Madness and
Chaos lie."
Arthur J. O'Dwyer
2007-02-19 03:05:10 UTC
Permalink
Post by James Harris
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer
to declare what a method /may/ throw?
[...]
Post by James Harris
My main objections to Java's way is that if aa calls bb calls cc ...
calls zz and I want to handle zz's errors in aa I still have to either
declare them in all intervening modules or catch a generic Exception
superclass and possibly encapsulate them in another object. The latter
is a kludge, IMHO. The former unfortunately obscures the program logic
and intention with foreign constructs or "mechanism."
Leaving aside the whole "does Java suck?" issue, ;) could some
Java expert please comment on the following scenario, which James'
scenario made me think of?

In C++, we can write

void higherLevel(void (*cbf)(int), int arr[], int n) {
for (int i=0; i < n; ++i)
cbf(arr[i]);
}

void callbackFunc(int x) {
if (x == 42)
throw "random exception";
}

void catcher() {
int arr[5] = {1,2,3,42,5};
try {
higherLevel(callbackFunc, arr, 5);
} catch (char *e) {
puts("Exception was thrown:");
puts(e);
}
}

How would the same thing be written in Java? Notice that the
function 'higherLevel' does not know (or need to know) anything
about the exception specification of 'callbackFunc'; I claim that
this is good design, because it means that 'higherLevel' can be
reused in other contexts.
The "contract" here is between 'catcher' and 'callbackFunc';
that is, 'catcher' should catch whatever 'callbackFunc' throws.
But 'higherLevel' is a neutral party in all this; it shouldn't
concern itself with those details.
C++ doesn't let us express that contract very well, unfortunately,
but it does let us write 'higherLevel' without the baggage. Does
Java?

(IIRC, in Java you'd use a bunch of classes or interfaces instead
of bare functions, but I hope you get the idea.)

And a topic for the c.l.misc crowd: What's the Right Way to
handle this scenario? Does C++ really get it right? How do real
functional languages do it?

-Arthur
Michael Rauscher
2007-02-19 10:37:58 UTC
Permalink
Post by Arthur J. O'Dwyer
In C++, we can write
...
Post by Arthur J. O'Dwyer
How would the same thing be written in Java? Notice that the
function 'higherLevel' does not know (or need to know) anything
about the exception specification of 'callbackFunc'; I claim that
this is good design, because it means that 'higherLevel' can be
reused in other contexts.
The "contract" here is between 'catcher' and 'callbackFunc';
No, there isn't any contract between these two.

catcher calls higherLevel, so one contract is between catcher and
higherLevel.

higherLevel calls cbf, so there's another contract: between higherLevel
and cbf.

Now, let's reformulate your code in Java:

interface CBF {
public void execute(int x);
}

public void higherLevel( CBF cbf, int arr[] ) {
for ( int i = 0; i < arr.length; i++ )
cbf.execute(arr[i]);
}

public void catcher() {
int arr[] = new int[]{1,2,3,42,5};
higherLevel( callBackFunc, arr );
}

There are two things to mention:

1. callBackFunc is not defined, yet.

2. If one looks at CBF one can see the obvious contract that must be
fullfilled when calling or *implementing* CBF#execute:
- the caller must provide one argument of type int.
- execute does not throw a checked exception.

Now, let's implement CBF:

CBF callBankFunc = new CBF() {
public void execute( int x ) {
if ( x == 42 )
throw new Exception();
}
};

This would lead to a compile-time error since the CBF promises that
there's no checked exception when 'execute' gets called.

If you really want to throw an exception, there are two ways. Either
throw an unchecked exception or if you a checked exception should be
thrown, declare it in CBF#execute's throws-clause.

E.g. throw new IllegalArgumentException("Invalid: 42");

Bye
Michael
Lew
2007-02-19 21:25:35 UTC
Permalink
Post by Michael Rauscher
CBF callBankFunc = new CBF() {
public void execute( int x ) {
if ( x == 42 )
throw new Exception();
}
};
This would lead to a compile-time error since the CBF promises that
there's no checked exception when 'execute' gets called.
If you really want to throw an exception, there are two ways. Either
throw an unchecked exception or if you a checked exception should be
thrown, declare it in CBF#execute's throws-clause.
E.g. throw new IllegalArgumentException("Invalid: 42");
Notice that Java supports either style, checked or runtime exceptions,
according to whether the ptrogrammer wishes to make the exception part of the
"contract". It also has a sort of imperfect closure mechanism in the use of
the CBF supertype, which while lacking many features of true closures is
enough for most tasks.

Very nice example.

- Lew
Arthur J. O'Dwyer
2007-02-20 00:47:00 UTC
Permalink
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
In C++, we can write
...
Post by Arthur J. O'Dwyer
How would the same thing be written in Java? Notice that the
function 'higherLevel' does not know (or need to know) anything
about the exception specification of 'callbackFunc' ...
The "contract" here is between 'catcher' and 'callbackFunc';
No, there isn't any contract between these two.
catcher calls higherLevel, so one contract is between catcher and
higherLevel.
higherLevel calls cbf, so there's another contract: between
higherLevel and cbf.
FWIW, you're wrong. The "contract" is obviously between the main
function 'catcher' and its helper function 'callbackFunc'. Now, I'll
agree that Java does not let us /express/ that contract; but that's
not the same thing as its not existing in the first place.
Post by Michael Rauscher
interface CBF {
public void execute(int x);
}
public void higherLevel( CBF cbf, int arr[] ) {
for ( int i = 0; i < arr.length; i++ )
cbf.execute(arr[i]);
}
public void catcher() {
int arr[] = new int[]{1,2,3,42,5};
higherLevel( callBackFunc, arr );
}
1. callBackFunc is not defined, yet.
2. If one looks at CBF one can see the obvious contract that must be
- the caller must provide one argument of type int.
- execute does not throw a checked exception.
3. 'catcher' doesn't contain a 'catch' clause, which makes its
name misleading at best. ;)
Post by Michael Rauscher
CBF callBankFunc = new CBF() {
public void execute( int x ) {
if ( x == 42 )
throw new Exception();
}
};
This would lead to a compile-time error since the CBF promises that there's
no checked exception when 'execute' gets called.
Okay, so you can't do it that way.
Post by Michael Rauscher
If you really want to throw an exception, there are two ways. Either throw
an unchecked exception
"Unchecked exception" being the Java equivalent of C++'s exceptions,
right? That is, they behave the same way as checked exceptions, but you
don't have to declare them in exception specifications.
http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
Post by Michael Rauscher
or if you a checked exception should be thrown,
declare it in CBF#execute's throws-clause.
That would be nice, but you just said that Java won't allow you to
do that. ("This would lead to a compile-time error ...") Unless of
course you propagate the exception specification all the way up into
'higherLevel', which would mean no code reuse in the presence of
checked exceptions.

It sounds like Java indeed has not yet found a magic bullet for
statically analyzing exception-handling. Not that there's anything wrong
with that. But it does mean that the comp.lang.misc discussion, which
is basically a search for a magic bullet, isn't totally pointless. Now
if only I can get the crosspost to c.l.m right this time...

-Arthur
Lew
2007-02-20 01:38:03 UTC
Permalink
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
or if you a checked exception should be thrown,
declare it in CBF#execute's throws-clause.
That would be nice, but you just said that Java won't allow you to
do that. ("This would lead to a compile-time error ...")
That is not what he said. In fact, he said the exact opposite.

He said the error would come from NOT declaring the checked exception in the
signature. That error would be fixed if CBF and its implementors declared the
exception for the method.
Post by Arthur J. O'Dwyer
CBF callBankFunc = new CBF() {
public void execute( int x ) {
if ( x == 42 )
throw new Exception();
}
};
This is what Michael said would cause a compiler error if execute() did not
declare the Exception in its signature.
Post by Arthur J. O'Dwyer
interface CBF {
public void execute(int x) throws Exception;
}
This is what Michael said would allow the implementing class to throw that
checked Exception, because now it is part of the signature. (The implementing
class would also need to include the throws clause in its signature in order
to throw the checked Exception, because it is part of the signature just like
the int argument is.)

- Lew
Michael Rauscher
2007-02-20 17:26:29 UTC
Permalink
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
catcher calls higherLevel, so one contract is between catcher and
higherLevel.
higherLevel calls cbf, so there's another contract: between
higherLevel and cbf.
FWIW, you're wrong. The "contract" is obviously between the main
function 'catcher' and its helper function 'callbackFunc'. Now, I'll
agree that Java does not let us /express/ that contract; but that's
not the same thing as its not existing in the first place.
You can't just ignore the higherLevel method.

Let's assume a specification that tells us that a value of 42 must not
be passed to callbackFunc. Further, assume there'd be a contract between
callbackFunc and catcher telling catcher.

Now, let's rewrite higherLevel:

void higherLevel( (void)(*cbf)(int), int arr[], int n ) {
try {
for ( int i = 0; i < n; i++ )
cbf(arr[i]);
} catch ( char *e ) {
}
}

With this, catcher will never catch an exception.

And now? What's about the contract between catcher and callbackFunc?
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
1. callBackFunc is not defined, yet.
2. If one looks at CBF one can see the obvious contract that must be
- the caller must provide one argument of type int.
- execute does not throw a checked exception.
3. 'catcher' doesn't contain a 'catch' clause, which makes its
name misleading at best. ;)
lol. I'm sorry. I have to concentrate on writing in English, so 3.
didn't came to my mind. I'm happy enough, if my writings don't contain
too much of incorrect English :)

Back to the topic:

catcher needs no catch clause since the contract contains no rule for this.

One may add a catch clause in order to catch unchecked exceptions, of
course.
Post by Arthur J. O'Dwyer
"Unchecked exception" being the Java equivalent of C++'s exceptions,
right? That is, they behave the same way as checked exceptions, but you
don't have to declare them in exception specifications.
Yes. E.g. dividing by zero would result in an ArithmeticException. As
Lew mentioned, checked exceptions are part of the contract - unchecked
are not.
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
or if you a checked exception should be thrown,
declare it in CBF#execute's throws-clause.
That would be nice, but you just said that Java won't allow you to
do that. ("This would lead to a compile-time error ...") Unless of
The example above ("This would lead to a compile-time error") was
related to the throw statement. This time I referred to the throws clause.
Post by Arthur J. O'Dwyer
course you propagate the exception specification all the way up into
'higherLevel', which would mean no code reuse in the presence of
checked exceptions.
I don't see anything that would be against code reuse.

If there's a throws clause it only means that an exception /might/ be
thrown. There's no need to throw an exception.

Example:

interface CBF {
public void execute( int x ) throws Exception;
}

Now, the Exception is part of the contract and higherLevel must take
care of it.

void higherLevel( CBF cbf, int arr[] ) throws Exception {
for ( int i = 0; i < arr.length; i++ )
cbf.execute(arr[i]);
}

The compiler ensures that the Exception is handled.

Bye
Michael
Arthur J. O'Dwyer
2007-02-20 18:04:11 UTC
Permalink
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
catcher calls higherLevel, so one contract is between catcher and
higherLevel.
higherLevel calls cbf, so there's another contract: between
higherLevel and cbf.
FWIW, you're wrong. The "contract" is obviously between the main
function 'catcher' and its helper function 'callbackFunc'. Now, I'll
agree that Java does not let us /express/ that contract; but that's
not the same thing as its not existing in the first place.
You can't just ignore the higherLevel method.
I /want/ to ignore the higherLevel method! Here's an analogy that
I think will be extremely clear to Lisp programmers, but maybe not to
C++/Java programmers: I can write

for (...) {
callbackFunc();
}

instead of

for (...) throws Exception {
callbackFunc();
}

Exceptions thrown by the inner callbackFunc() are quietly and
transparently passed out of the loop and up to the surrounding
context. So why can't I create my own "control structures" by
writing

... higherLevel(...) { ... }
higherLevel(callbackFunc);

instead of

... higherLevel(...) throws Exception { ... }
higherLevel(callbackFunc);
Post by Michael Rauscher
Let's assume a specification that tells us that a value of 42 must not be
passed to callbackFunc. Further, assume there'd be a contract between
callbackFunc and catcher telling catcher.
Yes, agreed. (Of course, as a C programmer myself, I'd object that
the contract isn't "don't pass me 42", but "if you pass 42 I'll throw
an exception." If the caller broke the contract as you stated it above,
I wouldn't be so nice as to waste my time throwing him an exception. ;)
Post by Michael Rauscher
void higherLevel( (void)(*cbf)(int), int arr[], int n ) {
try {
for ( int i = 0; i < n; i++ )
cbf(arr[i]);
} catch ( char *e ) {
}
}
With this, catcher will never catch an exception.
Oops!
Post by Michael Rauscher
And now? What's about the contract between catcher and callbackFunc?
You killed it, that's what happened! So clearly your way of
implementing higherLevel() is at fault. As the name "higherLevel"
implies, to me anyway, higherLevel() should pass exceptions through,
quietly and transparently, up to the surrounding context.
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
3. 'catcher' doesn't contain a 'catch' clause, which makes its
name misleading at best. ;)
lol. I'm sorry. I have to concentrate on writing in English, so 3. didn't
came to my mind. I'm happy enough, if my writings don't contain too much of
incorrect English :)
catcher needs no catch clause since the contract contains no rule for this.
Well, I put a 'catch' clause in my original C++ version, which is why
I made a big deal out of it. The Java was supposed to do the same thing
as the C++; that was the whole point!
Post by Michael Rauscher
One may add a catch clause in order to catch unchecked exceptions,
of course.
Right; and Java's unchecked exceptions do seem to solve the whole
problem.
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
or if you a checked exception should be thrown,
declare it in CBF#execute's throws-clause.
That would be nice, but you just said that Java won't allow you to
do that. ("This would lead to a compile-time error ...") Unless of
The example above ("This would lead to a compile-time error") was related to
the throw statement. This time I referred to the throws clause.
I just tested the code to make sure I wasn't mistaken --- I wasn't.
You get a compile-time error if you say:
(this is a complete translation unit):

interface CBF {
public void execute(int x);
}


class Foo {
public void higherLevel( CBF cbf, int arr[] ) {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}

public void catcher()
{
int arr[] = new int[] { 1, 2, 3, 42, 5 };

CBF callBackFunc = new CBF() {
public void execute(int x) {
if ( x == 42 )
throw new Exception();
}
};

try {
higherLevel( callBackFunc, arr );
} catch (Exception e) {
// handle exception somehow
}
}
}

Now change it to

CBF callBackFunc = new CBF() {
public void execute(int x) throws Exception {
if ( x == 42 )
throw new Exception();
}
};

Still an error; 'execute' doesn't match the interface. Change it to

interface CBF {
public void execute(int x) throws Exception;
}

Still an error; 'higherLevel' throws an undeclared exception. And now
we're borked, unless of...
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
...course you propagate the exception specification all the way up into
'higherLevel', which would mean no code reuse in the presence of
checked exceptions.
I don't see anything that would be against code reuse.
So let's make it

public void higherLevel( CBF cbf, int arr[] ) throws Exception {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}

Now I see two problems, but one of them might be a mirage. That one
is: what happens if we want to use higherLevel() with a callback
function that might throw something /else/? We'd have to make it

public void higherLevel( CBF cbf, int arr[] )
throws Exception, SomethingElse {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}

And then if we want to throw a third thing,

public void higherLevel( CBF cbf, int arr[] )
throws Exception, SomethingElse, AThirdThing {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}

Basically, every time our client code changes, we have to go find
our library and patch it. That's not code reuse.
Now, this "problem" is probably a mirage, because of the coincidence
that in Java, all checked exceptions derive from Exception (am I right?),
so we can just write "throws Exception" and we'll have covered all the
bases.

The more serious problem is, what happens if catcher2() wants to
perform higherLevel() on callback2(), and this time the contract
between the *2() functions does /not/ involve any exceptions being
thrown?

interface CBF {
public void execute(int x); // "throws Exception" or not, doesn't matter
}


class Foo2 {
// This is the same higher-level library function, reused.
// Pretend it's in a different translation unit.
public void higherLevel( CBF cbf, int arr[] ) throws Exception {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}

public void catcher2()
{
int arr[] = new int[] { 1, 2, 3, 42, 5 };

CBF callBack2 = new CBF() {
public void execute(int x) {
return; // no exceptions here!
}
};

higherLevel( callBack2, arr );
// no need for a catch; callBack2 doesn't throw
}
}

There's no way to make this code work, unless you are willing to do
one of three things:
(1) Change the library; i.e., give up on code reuse.
(2) Add spurious "catch" clauses to every use of 'higherLevel',
thus confusing the reader, since exceptions aren't being used in
this code.
(3) Add spurious "throws Exception" clauses to every function
in the program and a "catch" in main, again confusing the reader,
but at least conserving the vertical space.

Again I say: AFAICT, if you want C++-ish semantics in Java, you
use unchecked exceptions. There's no magic bullet in either language.
I appreciate your comment crossthread,
Post by Michael Rauscher
Of course, I can't give Java solutions to 'problems' that are not
feasible using Java. So, if the question had been if it's possible to
pass checked exceptions through methods without declaring them, then
I'd answered: no ;)
Truce? ;)

-Arthur
Robbert Haarman
2007-02-20 18:47:53 UTC
Permalink
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
catcher calls higherLevel, so one contract is between catcher and
higherLevel.
higherLevel calls cbf, so there's another contract: between
higherLevel and cbf.
FWIW, you're wrong. The "contract" is obviously between the main
function 'catcher' and its helper function 'callbackFunc'. Now, I'll
agree that Java does not let us /express/ that contract; but that's
not the same thing as its not existing in the first place.
You can't just ignore the higherLevel method.
I /want/ to ignore the higherLevel method! Here's an analogy that
I think will be extremely clear to Lisp programmers, but maybe not to
C++/Java programmers: I can write
for (...) {
callbackFunc();
}
instead of
for (...) throws Exception {
callbackFunc();
}
Exceptions thrown by the inner callbackFunc() are quietly and
transparently passed out of the loop and up to the surrounding
context. So why can't I create my own "control structures" by
writing
... higherLevel(...) { ... }
higherLevel(callbackFunc);
instead of
... higherLevel(...) throws Exception { ... }
higherLevel(callbackFunc);
Meh, having to write "throws Exception" when you define higherLevel is
not nearly as bad as having to write "throws Exception" each time you
write a for loop.

Having said that, I completely agree that it would be nice if higher
order functions would simply pass along the exceptions from callbacks
passed to them. And of course, removing the mandatory throws clause
would accomplish just that. Unfortunately, that doesn't even begin to
solve the ugliness of higher order functions in Java...
Post by Arthur J. O'Dwyer
So let's make it
public void higherLevel( CBF cbf, int arr[] ) throws Exception {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}
Now I see two problems, but one of them might be a mirage. That one
is: what happens if we want to use higherLevel() with a callback
function that might throw something /else/? We'd have to make it
public void higherLevel( CBF cbf, int arr[] )
throws Exception, SomethingElse {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}
No. SomethingElse will either not be a checked exception, which means it
does not have to appear in the throws clause, or it will be a subclass
of Exception, which means it's already covered.

However, you _would_ have to use instanceof or upcasts to get back from
Exception to the actual type, if necessary. If you write

someMethod(...) throws Exception {
...
}

try {
someMethod(...);
catch(IOException ioe) {
...
}

The compiler will complain that someMethod does not throw IOException,
even if the body of someMethod does.
Post by Arthur J. O'Dwyer
The more serious problem is, what happens if catcher2() wants to
perform higherLevel() on callback2(), and this time the contract
between the *2() functions does /not/ involve any exceptions being
thrown?
interface CBF {
public void execute(int x); // "throws Exception" or not, doesn't matter
}
class Foo2 {
// This is the same higher-level library function, reused.
// Pretend it's in a different translation unit.
public void higherLevel( CBF cbf, int arr[] ) throws Exception {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}
public void catcher2()
{
int arr[] = new int[] { 1, 2, 3, 42, 5 };
CBF callBack2 = new CBF() {
public void execute(int x) {
return; // no exceptions here!
}
};
higherLevel( callBack2, arr );
// no need for a catch; callBack2 doesn't throw
}
}
There's no way to make this code work, unless you are willing to do
(1) Change the library; i.e., give up on code reuse.
(2) Add spurious "catch" clauses to every use of 'higherLevel',
thus confusing the reader, since exceptions aren't being used in
this code.
(3) Add spurious "throws Exception" clauses to every function
in the program and a "catch" in main, again confusing the reader,
but at least conserving the vertical space.
I am starting to think that the best way to write higher order functions
in Java would be to have the higher order function catch exceptions from
the callback and wrap them in some sort of unchecked exception, leaving
it up to the caller (of the higher order method) whether these
exceptions will be handled or not.

On second thought, even this solution isn't satisfactory, because now
(1) the compiler won't enforce checked exceptions anymore, and (2) the
nested exceptions have to be unboxed, and getting back to the original
exception classes will require instanceof/upcast/whatever ugliness.
Arggh...
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
Of course, I can't give Java solutions to 'problems' that are not
feasible using Java. So, if the question had been if it's possible to
pass checked exceptions through methods without declaring them, then
I'd answered: no ;)
Fair enough. Of course, since we started out discussing language
_design_, the question to ask at this point is "should it be possible"?
I think the case for "yes" has been made, by demonstrating that
functional programming becomes ugly otherwise. But then again, it's
already clear that Java wasn't designed for functional programming, so
perhaps a bit more ugliness isn't a concern.

Regards,

Bob
--
Furious activity is no substitute for understanding.

-- H.H. Williams
Michael Rauscher
2007-02-20 19:52:45 UTC
Permalink
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
catcher calls higherLevel, so one contract is between catcher and
higherLevel.
higherLevel calls cbf, so there's another contract: between
higherLevel and cbf.
FWIW, you're wrong. The "contract" is obviously between the main
function 'catcher' and its helper function 'callbackFunc'. Now, I'll
agree that Java does not let us /express/ that contract; but that's
not the same thing as its not existing in the first place.
You can't just ignore the higherLevel method.
I /want/ to ignore the higherLevel method! Here's an analogy that
I know, but you can't :)
Post by Arthur J. O'Dwyer
I think will be extremely clear to Lisp programmers, but maybe not to
C++/Java programmers: I can write
This also applies to Java programmers.
Post by Arthur J. O'Dwyer
Exceptions thrown by the inner callbackFunc() are quietly and
transparently passed out of the loop and up to the surrounding
context. So why can't I create my own "control structures" by
writing
Becaus it's Java. No function-pointers, no self-made control structures.
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
Let's assume a specification that tells us that a value of 42 must not
be passed to callbackFunc. Further, assume there'd be a contract
between callbackFunc and catcher telling catcher.
Yes, agreed. (Of course, as a C programmer myself, I'd object that
the contract isn't "don't pass me 42", but "if you pass 42 I'll throw
an exception."
Of course, you're right.
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
And now? What's about the contract between catcher and callbackFunc?
You killed it, that's what happened! So clearly your way of
implementing higherLevel() is at fault. As the name "higherLevel"
Ah! I thought you want to ignore higherLevel... ;)

So I could easily kill contracts between a client and a supplier by...
...writing a method?
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
or if you a checked exception should be thrown,
declare it in CBF#execute's throws-clause.
That would be nice, but you just said that Java won't allow you to
do that. ("This would lead to a compile-time error ...") Unless of
The example above ("This would lead to a compile-time error") was
related to the throw statement. This time I referred to the throws clause.
I just tested the code to make sure I wasn't mistaken --- I wasn't.
It was the compiler (not me - sorry) that told you to add throws-clauses
to CBF and higherLevel. Nice :)
Post by Arthur J. O'Dwyer
Post by Michael Rauscher
I don't see anything that would be against code reuse.
So let's make it
public void higherLevel( CBF cbf, int arr[] ) throws Exception {
for (int i=0; i < arr.length; ++i)
cbf.execute(arr[i]);
}
Now I see two problems, but one of them might be a mirage. That one
is: what happens if we want to use higherLevel() with a callback
function that might throw something /else/? We'd have to make it
java.lang.Exception is the mother of all exceptions. So, you can leave
higherLever as it is and simple throw an arbitrary exception.
Post by Arthur J. O'Dwyer
Now, this "problem" is probably a mirage, because of the coincidence
that in Java, all checked exceptions derive from Exception (am I right?),
so we can just write "throws Exception" and we'll have covered all the
bases.
Yep.
Post by Arthur J. O'Dwyer
The more serious problem is, what happens if catcher2() wants to
perform higherLevel() on callback2(), and this time the contract
between the *2() functions does /not/ involve any exceptions being
thrown?
The contract is specified by the interface CBF. Design by contract not
implementation.
Post by Arthur J. O'Dwyer
There's no way to make this code work, unless you are willing to do
(1) Change the library; i.e., give up on code reuse.
(2) Add spurious "catch" clauses to every use of 'higherLevel',
thus confusing the reader, since exceptions aren't being used in
this code.
(3) Add spurious "throws Exception" clauses to every function
in the program and a "catch" in main, again confusing the reader,
but at least conserving the vertical space.
The right answer is (2). But the added catch-clauses aren't spurious
since higherLevel uses an /interface/: CBF.

Look at the Javadocs, they're full of interfaces. Anybody can write
methods that makes use of them. And nobody needs to know about the
details of their implementation.

I don't mind if one implementation in fact throws exceptions. If the
interface says that there might an exception be thrown, then I've to
handle this situation.
Post by Arthur J. O'Dwyer
Again I say: AFAICT, if you want C++-ish semantics in Java, you
use unchecked exceptions. There's no magic bullet in either language.
Sure.

Bye
Michael
Jesu81Rebix
2007-02-21 05:29:25 UTC
Permalink
Post by James Harris
I have a number of books on Java but none seem to answer the
fundamental question on throws clauses: /why/ force the programmer to
declare what a method /may/ throw?
To quote one: "If you write a method that throws an exception, then
the Java compiler wil require that you do one of two things: you must
either declare that the method throws the exception using the 'throws'
keyword, or else you must provide a catch exception handler to catch
that exception." - Java Programming Explorer.
Is there really value in Java's behaviour? Or is this an unnecessary
burden on the programmer? Why not simply accept exceptions can be
thrown which are not listed, and deal with them in the innermost catch
clause which matches?
Conversely, if there is a chain of methods: aa calls bb calls cc calls
dd, and dd declares that it throws FileNotFoundException, if we don't
want to handle it in cc do we need to declare that it also throws
FileNotFoundException... and so on through callers to cc etc?
In terms of code maintenance, if dd could once throw a given exception
but now, because the relevant code has been removed, it cannot does cc
still need to provide for handling the exception simply /because/ it
is listed in dd's throws clause?
Any replies appreciated and please keep comp.lang.misc in the
crosspost list as it's relevant to language design principles. Thanks.
The throws package is very useful. because we can understand which
exception has been held. If we use try .... catch is better than
throws. In try.... catch we found the particular exception only
Continue reading on narkive:
Loading...