can't throw

A

Arne Vajhøj

[...]
But given that languages invented after Java chose not to
implement checked exceptions, then we must conclude that
it has not caught on.

(primarily thinking of C# and Scala here)

So the benefits are not that obvious to everyone.

And more to the point, those other languages do not seem to suffer greatly,
if at all, from the lack of checked exceptions.

They do not seem to suffer in the sense that it does not impact
popularity or general reliability.

It has had a big impact on coding style (at least for C# - I have not
seen sufficient with Scala code to say anything about Scala). The
typical C# program does less exception handling than the typical
Java program.

In theory more exception handling should be better. But I guess
that a pretty big portion of that exception handling simply is
not good enough.
For whatever reason, I've never found checked exceptions a compelling
feature. It's absolutely in the right spirit, one which I agree
wholeheartedly with. And yet I find that at least in the Java
implementation, it seems to create more headaches than it prevents.

It is PITA for writing 25 lines of demo code.

But I really don't see much headache in real programs. One
need to think about the issue anyway.

Arne
 
A

Arne Vajhøj

To me, it also seems as if it would be a good idea, but using it
is awkward. In some coursework, I used a Java cryptographic system.
It had a lot of exceptions to handle so my code had a lot of catches.
Because I did not know what was thrown, I wrote my code without them
and then added whatever the compiler stated was missing. In those
catches, there really was not anything that I could do other than
reporting the error.

Sounds more like a design problem.

You should catch exceptions at the level where it can be handled
(either where a method can do something that will allow the program
to continue to run or at the outer level where the program can be
terminated).

There is just one thing that is worse than catch everything possible,
report it and continue without doing anything or terminating everywhere
in the code - and that is doing the same thing except not reporting it.

Way too many exceptions is typical a sign of code not properly divided
in layers/components. Such throw layer/component specific exceptions but
hides all the implementation specific exceptions.
I prefer reading the main flow of execution as a high-level
story. Catches interrupt this. When there are a lot of catches, they
make the main code harder to find.

You should not really have more catches due to checked exceptions.

You should only catch exceptions that you can do something useful
about it. That an exception is checked does not change whether you can
so something useful about it. It just reminds you of its existence.

Arne
 
G

Gene Wirchenko

Sounds more like a design problem.

I did not write the crypto package.
You should catch exceptions at the level where it can be handled
(either where a method can do something that will allow the program
to continue to run or at the outer level where the program can be
terminated).

Well, the level I caught the exception at was the individual
calls to the package. There were so many exceptions, and it was
really irrelevant what the exception was. Whatever it was, it meant
that my program had failed. Writing the glue code to catch each of
these exceptions was simply make-work.
There is just one thing that is worse than catch everything possible,
report it and continue without doing anything or terminating everywhere
in the code - and that is doing the same thing except not reporting it.

Way too many exceptions is typical a sign of code not properly divided
in layers/components. Such throw layer/component specific exceptions but
hides all the implementation specific exceptions.


You should not really have more catches due to checked exceptions.

You should only catch exceptions that you can do something useful
about it. That an exception is checked does not change whether you can
so something useful about it. It just reminds you of its existence.

I had to catch the exceptions or get a compilation error for each
one I missed.

Sincerely,

Gene Wirchenko
 
A

Arne Vajhøj

I did not write the crypto package.

No.

But I assume you wrote the code where yous ay you put in all
those catch.
Well, the level I caught the exception at was the individual
calls to the package. There were so many exceptions, and it was
really irrelevant what the exception was. Whatever it was, it meant
that my program had failed. Writing the glue code to catch each of
these exceptions was simply make-work.

Definitely sounds as if it was a big mistake to catch the exceptions
where they happened.
I had to catch the exceptions or get a compilation error for each
one I missed.

No.

You has to catch them *or* pass them back the caller by adding throws to
the method signature.

If the method can not really do anything about the exception then
the last option is what should be used.

Arne
 
A

Arne Vajhøj

No.

You has to catch them *or* pass them back the caller by adding throws to
the method signature.

If the method can not really do anything about the exception then
the last option is what should be used.

Not:

public class Wrong {
public static class ExceptionA extends Exception {
}
public static class ExceptionA1 extends ExceptionA {
}
public static class ExceptionA2 extends ExceptionA {
}
public static class ExceptionA3 extends ExceptionA {
}
public static class ExceptionB extends Exception {
}
public static class ExceptionB1 extends ExceptionB {
}
public static class ExceptionB2 extends ExceptionB {
}
public static class ExceptionB3 extends ExceptionB {
}
public static class ExceptionC extends Exception {
}
public static class ExceptionC1 extends ExceptionC {
}
public static class ExceptionC2 extends ExceptionC {
}
public static class ExceptionC3 extends ExceptionC {
}
public static class SomeLib {
public void a() throws ExceptionA1, ExceptionA2 {
}
public void aa() throws ExceptionA2, ExceptionA3 {
}
public void b() throws ExceptionB1, ExceptionB2 {
}
public void bb() throws ExceptionB2, ExceptionB3 {
}
public void c() throws ExceptionC1, ExceptionC2 {
}
public void cc() throws ExceptionC2, ExceptionC3 {
}
}
public static void m2() {
SomeLib lib = new SomeLib();
try {
lib.a();
lib.aa();
lib.b();
lib.bb();
lib.c();
lib.cc();
} catch (ExceptionA1 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionA2 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionA3 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionB1 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionB2 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionB3 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionC1 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionC2 e) {
e.printStackTrace();
System.exit(1);
} catch (ExceptionC3 e) {
e.printStackTrace();
System.exit(1);
}
}
public static void m1() {
m2();
}
public static void main(String[] args) {
m1();
}
}

but:

public class Correct {
public static class ExceptionA extends Exception {
}
public static class ExceptionA1 extends ExceptionA {
}
public static class ExceptionA2 extends ExceptionA {
}
public static class ExceptionA3 extends ExceptionA {
}
public static class ExceptionB extends Exception {
}
public static class ExceptionB1 extends ExceptionB {
}
public static class ExceptionB2 extends ExceptionB {
}
public static class ExceptionB3 extends ExceptionB {
}
public static class ExceptionC extends Exception {
}
public static class ExceptionC1 extends ExceptionC {
}
public static class ExceptionC2 extends ExceptionC {
}
public static class ExceptionC3 extends ExceptionC {
}
public static class SomeLib {
public void a() throws ExceptionA1, ExceptionA2 {
}
public void aa() throws ExceptionA2, ExceptionA3 {
}
public void b() throws ExceptionB1, ExceptionB2 {
}
public void bb() throws ExceptionB2, ExceptionB3 {
}
public void c() throws ExceptionC1, ExceptionC2 {
}
public void cc() throws ExceptionC2, ExceptionC3 {
}
}
public static void m2() throws ExceptionA, ExceptionB, ExceptionC {
SomeLib lib = new SomeLib();
lib.a();
lib.aa();
lib.b();
lib.bb();
lib.c();
lib.cc();
}
public static void m1() throws ExceptionA, ExceptionB, ExceptionC {
m2();
}
public static void main(String[] args) {
try {
m1();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

Arne
 
R

Roedy Green

In particular, I'm subclassing Thread and can't throw an Exception in the run method. I suspect this is a more general issue though.

try throwing an IllegalArgumentException or the like instead. You
don't need to declare it.
 
L

Lew

Arne said:
It makes a lot of sense if you are API centric.

A contract "I will either return a value of type X or throw
one of the exceptions E1,...,En" seems a lot more strict than
"I will either return a value of type X or throw an exception
but I will not tell you which".

Agreed, although some chafe at the restriction, and point out
that other code works just fine without such things.

In some cases that's because the platform implicitly supports
some exception-handling mechanism that wraps more than what
Java's does, or the language uses some assertion-like mechanism
to render exceptions moot.

Java's checked exceptions serve a real but optional need, not
only to be strict, but to warn API users (yes, this is an
API-centric or API-ontologic view) of expected exceptions.

Otherwise all exceptions are RuntimeExceptions or worse, and
by definition come as a surprise.

By convention and just the way it works out, RuntimeExceptions
are for program(mer) errors. The infamous NPE is an example.
Most use cases are better served by explicit null guards than
exception tosses.

Not to say that RuntimeExceptions aren't useful; they are.
The suggestions here to wrap checked exceptions in them
are an example. That's because an exception visible to one
thread from another are a surprise, and most likely a
program(mer) error. *Especially* because checked exceptions
are by definition expected and should usually not propagate
outside their thread.

Into logs, yes. As exceptions, not.

Throwing 'Exception' itself is a Dark Art. You can play
with poison - there are valid reasons to do so.

'Error' and raw 'Throwable' - whatever the interpretation here,
it's a bad-ass event.

Like all programming idioms, when you write exceptions
you should have a good flair for their purpose. Arne makes
sense - balances a case for their utility with a recognition
of both their limits and that people do without them.

As he says overthread, "One needs to think about the issue anyway."
Exceptions provide one way to express the decisions you make on
how to handle it.

A key for me is an idea that some code path is exceptional,
and another is a "happy" path. Another key is that I pair
(not) throwing an exception with an assertion.

Example:

public void foo(Bar param)
{
if (param == null || param.getBaz() != State.READY)
{
throw new IllegalStateException("Bad param "+param);
}
assert param != null && param.getBaz() == State.READY;
. . .
}
 
R

Robert Klemme

Actually, you can handle exceptions from a Thread. There is the
UncaughtExceptionHandler:
<http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html>


Though the only valuable use I have ever seen from this is in logging
those failures differently than the default output.

Right, I completely forgot about that. The issue with this is that you
have far less context than inside method run(). So handling there is
certainly preferred.
Agreed. If you need some other code to propagate an Exception, you need
to pass that information along. Exceptions are meant to unwind the
stack. For most practical purposes a Thread's run() method really has no
stack to unwind. Even if you could throw an Exception from it, where
would that Exception go? Who's going to deal with it?

.... other than the default uncaught exception handler. Exactly.

Kind regards

robert
 
G

Gene Wirchenko

On Wed, 12 Sep 2012 18:24:56 -0400, Arne Vajhøj wrote:
[snip]
In theory more exception handling should be better. But I guess
that a pretty big portion of that exception handling simply is
not good enough.

It does tend to get something just to shut up the compiler.
In theory. But it's not at all clear to me that the extra exception
handling in Java isn't just to work around the fact that checked exceptions
exist.

[snipped middle]
But when a language makes a programmer jump through hoops just to comply
with a syntactical requirement, where in other languages the lack of
hoop-jumping does not appear to result in less-reliable or
less-maintainable code, I start to question just how useful that
hoop-jumping is, even as I tend to agree with the underlying sentiment that
led to it.

Nicely stated. I am of the same view, and you captured it very
well.

Unintended consequences are still consequences.

It may not be nearly as elegant, but I still prefer BASIC's ON
ERROR GOTO handling. Yes, one had to sort through the error numbers,
but that made it easier in some ways. One could code something to
handle the few cases where there was a specific handling and then use
a catch-all for the rest.

Sincerely,

Gene Wirchenko
 
R

Robert Klemme

It may not be nearly as elegant, but I still prefer BASIC's ON
ERROR GOTO handling. Yes, one had to sort through the error numbers,
but that made it easier in some ways. One could code something to
handle the few cases where there was a specific handling and then use
a catch-all for the rest.

Well, you can do _that_ in Java, too.

I find the distinction between checked and unchecked exceptions pretty
good - although the distribution of exception types across these
categories does not always seem to be wisely made in the standard library.

Cheers

robert
 
L

Lew

And you can't do that with Java exceptions?
Well, you can do _that_ in Java, too.

Ah, I thought so.

So what was that advantage of BASIC's approach again?
I find the distinction between checked and unchecked exceptions pretty
good - although the distribution of exception types across these
categories does not always seem to be wisely made in the standard library.

API writing is a Dark Art, or rather a Dark Artish approach to programming generally.

It's arguably the best approach.

But designing the exception API is Darker Art.

People who complain about checked exceptions always take the client point of
view, and always blame Java.

(Counterexamples welcome.)

But if they are so bad, why do API writers opt to use them?

I know the answer. Do you?

Regardless, why blame Java for the API writer's choice?

As for comparing to other languages that don't have checked exceptions,
that's utter bullshit. Bullshit, I say.

You can't compare the API writer's choices when they don't have the same
options.

So writers of code in those other, lesser languages that don't have checked
exceptions resort to some other idiom, simply because the checked
exception idiom doesn't exist.

So of course it works, because they use the mechanisms that their
languages *do* provide. Duh, and double-duh.

Drawing the conclusion that checked exceptions aren't necessary,
given some other mechanism to accomplish equivalent goals,
is hardly insightful. Drawing the conclusion from that evidence that
checked exceptions are somehow inferior to those other mechanisms
is fallacious.

What is valid is to compare decisions to use or not use checked
exceptions in environments where they are available.

Interesting then, that in such environments that good programmers
find checked exceptions useful.

If you don't like their insistence that you honor the exception contract
they designed, don't use their libraries. Just like if you don't like their
insistence that you honor the argument contract they designed, don't
use their libraries.

Just don't blame Java for providing the API writer the tools to force you
to deal with something they thought important enough to force you to
deal with. Thank God and the Java Founders that checked exceptions
were available to that API writer to enforce that contract on you, otherwise
a) they couldn't ensure you honor certain robustness requirements, and
b) you couldn't be sure of exactly what exceptional situations they really
insist you handle.
 
G

Gene Wirchenko

Well, you can do _that_ in Java, too.

I am not surprised. Unfortunately, I never learned that.
Beginning Java texts that I have seen do not cover it. With BASIC,
handling errors was with only one error handler so it was forced to do
it that way (and sometimes, it was covered).
I find the distinction between checked and unchecked exceptions pretty
good - although the distribution of exception types across these
categories does not always seem to be wisely made in the standard library.

Java has too many distinctions that are not easily (or
often-enough) made and that can catch Java newbies.

Maybe, it was too much of trying to be everything to everybody?

Sincerely,

Gene Wirchenko
 
G

Gene Wirchenko

And you can't do that with Java exceptions?


Ah, I thought so.

So what was that advantage of BASIC's approach again?

It is obvious that you can do it that way.

[snip]

Sincerely,

Gene Wirchenko
 
R

Robert Klemme

I am not surprised. Unfortunately, I never learned that.
Beginning Java texts that I have seen do not cover it. With BASIC,
handling errors was with only one error handler so it was forced to do
it that way (and sometimes, it was covered).

I wasn't aware that this seems to be such a mystery. The basic (!)
mechanism is pretty simple: exception handler order matters: the first
matching handler is used. So you can place handlers for classes down
the exception inheritance hierarchy at the front and place handlers for
classes further up later. In an extreme case use a catch block with
RuntimeException, Exception or Throwable as last one.
Java has too many distinctions that are not easily (or
often-enough) made and that can catch Java newbies.

Maybe, it was too much of trying to be everything to everybody?

I believe what you describe is rather an effect of the massive success
the language has had. That success a) led to a prolonged life and b)
steered more resources into the development of the language, libraries
and frameworks. For another language people might not have bothered to
write another IO library. Now there are is more than one around to
maintain compatibility and that makes the language look inconsistent -
even though it's just history showing. Same story with Vector and
ArrayList or synchronized vs. java.util.concurrent.locks (where one is
really a language feature and the other a library) or Date vs. Calendar.
As Lew said, you need darn good library designers to get it right the
first time. But at least you can see that newer parts of the library
are better than older parts. I find that good even though it increases
the volume of library API to learn.

Cheers

robert
 
L

Lew

Here you go, the cure for your ignorance of how to use Java exceptions:
http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
I wasn't aware that this seems to be such a mystery. The basic (!)

It isn't if you read the tutorial.

The place where everyone is recommended to begin learning Java.
mechanism is pretty simple: exception handler order matters: the first
matching handler is used. So you can place handlers for classes down

From the tutorial: " The runtime system invokes the exception handler
"when the handler is the first one in the call stack whose ExceptionType
matches the type of the exception thrown."
the exception inheritance hierarchy at the front and place handlers for
classes further up later. In an extreme case use a catch block with
RuntimeException, Exception or Throwable as last one.

As illustrated in the tutorial: "By catching any IOException that's not caught
by the first handler, . . . "

"The first kind of exception is the checked exception. These are exceptional
conditions that a well-written application should anticipate and recover from."

Unless they read the tutorials.

Maybe it was a case of not RTFM?

Blaming the language for one's failure to study is an unworthy act.
I believe what you describe is rather an effect of the massive success

This doesn't apply to exceptions, most of whose functionality has been
the same in Java for a long time.
the language has had. That success a) led to a prolonged life and b)
steered more resources into the development of the language, libraries
and frameworks. For another language people might not have bothered to
write another IO library. Now there are is more than one around to
maintain compatibility and that makes the language look inconsistent -
even though it's just history showing. Same story with Vector and
ArrayList or synchronized vs. java.util.concurrent.locks (where one is
really a language feature and the other a library) or Date vs. Calendar.

As Lew said, you need darn good library designers to get it right the
first time. But at least you can see that newer parts of the library
are better than older parts. I find that good even though it increases
the volume of library API to learn.

But learning about Exceptions isn't an API exercise, at this level, but
a language-comprehension issue and whether one bothers to read the
elementary introductions to the language.

Or then whines that the language is too hard because they didn't bother
to learn the most elementary aspects of it in the first place.
 
R

Robert Klemme

Personally, I think it was a design flaw to tie the checked /
unchecked to the class hierarchy. An exception's class corresponds to
a particular error type, but the severity of a particular type of
error, and wheter we can expect the client to be able to recover from
it or not, depends on the context.

The choice of checked / unchecked should be made statically _at the
point of the throw statement_,

Let's see what the consequences of this would be:

1. we need new syntax (e.g. a new keyword), in order to make that
distinction. So it's either
throw checked new IllegalStateException("You can't do that right now.")
throw_checked new IllegalStateException("You can't do that right now.")

2. The complier needs to enforce all exceptions thrown with "throw
checked" are declared in the throws clause.

OK so far, no issues there.

3. Now, assume we have a section of code which throws the same exception
type checked and unchecked. That section is embedded in a try block.
Now we have a catch clause for this exception type attached to the try
block. This prompts the question: which of the thrown exceptions does
the catch block handle - only the checked throws or also unchecked throws?

3a. It handles both. This leads to the unsatisfactory situation where
the same catch block needs to handle programmer errors (now
RuntimeException and subclasses) and other errors which are actually
expected. That's not good since programmer errors (and catastrophic
situations like OOM are usually handled quite close to Thread.run, i.e.
further up the call stack.

3b. The programmer can decide, so we need a new syntax again:

catch checked ( IllegalStateException e )

This will only catch checked exceptions. Do we now need an additional
syntax for "unchecked", e.g.

catch unchecked ( IllegalStateException e )

And what do we do if we want to cover both cases (e.g. because we just
want to print the error)? Do we then do this?

catch checked, unchecked ( IllegalStateException e )

Or do we use the current form to mean "catch both"?

catch ( IllegalStateException e )

In which way we resolve these questions it's obvious that one can easily
forget a keyword or make a different error so one ends handling other
exceptions than intended.

Given the fact that the type of exception also describes the type of
error and that in turn is related to the classification "programmer
error" / "no programmer error" I am not so sure whether the additional
complication your distinction at call site introduces is actually
worthwhile.

Kind regards

robert
 
R

Robert Klemme

Plain catch statements, "catch ( SomeException ex )", only catches
checked exceptions and it's illegal to have a plain catch statement
for an exception that can not be thrown (checked) in the try
block.

"Catch unchecked" catches both checked and unchecked versions of the
exception. Having only an unchecked catch for a given exception that
can be thrown checked in the try block is legal, but causes a compiler
warning: the preferred is to have two separate catch statements for
checked and unchecked versions of that exception.

It's not foolproof (fools are just so darned clever at times), but it
strikes me as safe enough to be practical.

My point was not that it can't be made "safe". I rather questioned
whether the additional complexity introduced in the language would be
beneficial (even if we let compatibility issues aside for the moment).

Cheers

robert
 
G

Gene Wirchenko

[snip]
Or then whines that the language is too hard because they didn't bother
to learn the most elementary aspects of it in the first place.

Just try finding the most elementary aspects in all that bloat.

The problem is not so much reading the docs; it is finding the
correct ones. When one is just starting, it is difficult to sort the
wheat from the chaff.

Sincerely,

Gene Wirchenko
 
G

Gene Wirchenko

On Sun, 16 Sep 2012 22:36:00 +0200, Robert Klemme

[snip]
My point was not that it can't be made "safe". I rather questioned
whether the additional complexity introduced in the language would be
beneficial (even if we let compatibility issues aside for the moment).

The architecture astronauts got Java long ago.

While C has many trade-offs that I disagree with, one thing that
they got right is that it is a small language.

Sincerely,

Gene Wirchenko
 
R

Robert Klemme

On Sun, 16 Sep 2012 22:36:00 +0200, Robert Klemme

[snip]
My point was not that it can't be made "safe". I rather questioned
whether the additional complexity introduced in the language would be
beneficial (even if we let compatibility issues aside for the moment).

The architecture astronauts got Java long ago.

While C has many trade-offs that I disagree with, one thing that
they got right is that it is a small language.

But "small" is not a value in itself. Programming languages are tools
and a small language might have less complexity than necessary to solve
today's problems. If you can learn it fast (because it is small) but
then you need to go through hoops every day to write the code that you
need to write, what have you gained?

Cheers

robert
 

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,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top