Why does Java require the throws clause? Good or bad language design?

R

Robbert Haarman

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.
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
 
L

Lew

Robbert said:
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
 
L

Lew

Robbert said:
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
 
B

Bent C Dalager

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
 
R

Robbert Haarman

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
 
R

Robbert Haarman

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)
 
C

Chris Uppal

Robbert said:
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
 
C

Chris Uppal

Lew said:
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
 
M

Michael Rauscher

Arthur said:
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);
} catch ( char *e ) {
}
}

With this, catcher will never catch an exception.

And now? What's about the contract between catcher and callbackFunc?
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.
"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.
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.
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);
}

The compiler ensures that the Exception is handled.

Bye
Michael
 
A

Arthur J. O'Dwyer

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);

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. ;)
Now, let's rewrite higherLevel:

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

With this, catcher will never catch an exception.


Oops!
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.

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.

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!
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.

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);
}

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...
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);
}

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);
}

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);
}

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);
}

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,
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
 
R

Robbert Haarman

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...
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);
}

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);
}


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.
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);
}

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.


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...

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
 
M

Michael Rauscher

Arthur said:
I /want/ to ignore the higherLevel method! Here's an analogy that

I know, but you can't :)
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.
> 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.
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.
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?

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 :)
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);
}

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.
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.

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.
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.

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.
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
 
C

Chris Uppal

Chris said:
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).

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.

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".

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
 
G

Guest

Robbert said:
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).
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
 
L

Lew

Robbert said:
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
 
G

Guest

Robbert said:
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.


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.
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.
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
 
J

Jesu81Rebix

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
 
R

Robbert Haarman

But why make the functionality hidden for the programmer ?

What functionality?
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).

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
 
R

Robbert Haarman

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
 
R

Robbert Haarman

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.
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?
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top