why does catching errors that aren't thrown give syntax errors?

Y

yawnmoth

public class Test01
{
public static void main() {
try {} catch (java.io.IOException e) {}
}
}

When I run that, I get the following:

Test01.java:4: exception java.io.IOException is never thrown in body
of corresponding try statement
try {} catch (java.io.IOException e) {}
^
1 error

My question is... why? Giving a syntax error over this seems about
as appropriate as giving a syntax error for "if (false)". In both
cases, although it may not serve a lot of point in a finished product,
it may be useful for debugging. If I comment out a line that may
(conditionally) throw java.io.IOException, it's annoying having to
comment out a whole slew of other lines, as well. Same thing for "if
(false)". That's easier than commenting out the whole if statement
(especially if there aren't any else's present).
 
A

Arne Vajhøj

yawnmoth said:
public class Test01
{
public static void main() {
try {} catch (java.io.IOException e) {}
}
}

When I run that, I get the following:

Test01.java:4: exception java.io.IOException is never thrown in body
of corresponding try statement
try {} catch (java.io.IOException e) {}
^
1 error

My question is... why? Giving a syntax error over this seems about
as appropriate as giving a syntax error for "if (false)". In both
cases, although it may not serve a lot of point in a finished product,
it may be useful for debugging. If I comment out a line that may
(conditionally) throw java.io.IOException, it's annoying having to
comment out a whole slew of other lines, as well. Same thing for "if
(false)". That's easier than commenting out the whole if statement
(especially if there aren't any else's present).

The Java language was designed that way.

http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.20

<quote>
It is a compile-time error if a catch clause catches checked exception
type E1 but there exists no checked exception type E2 such that all of
the following hold:

* E2 <: E1
* The try block corresponding to the catch clause can throw E2
* No preceding catch block of the immediately enclosing try
statement catches E2 or a supertype of E2.

unless E1 is the class Exception.
</quote>

The reasons is most likely to avoid not needed catch statement in
final code.

And yes it can be irritating during development.

But apparently the final code has gotten priority over nuisances
for the developer.

And I agree with that.

Arne
 
J

Joshua Cranmer

yawnmoth said:
My question is... why? Giving a syntax error over this seems about
as appropriate as giving a syntax error for "if (false)".

Well, |if (false)| is not a compile-time error.

In any case, the short answer is that catching a non-thrown exception is
a syntax error as prescribed by the JLS. But you're probably wondering
why it is a syntax error.

I can't claim to know what the Java developers were thinking, but I'm
going to guess:

Most forms of unreachable code are forbidden, probably with the intent
of easing development by getting rid of code that appears to be called
but is, in fact, never called. |if (false)| is specifically allowed on
the pretext that debug-specific code would be run via an if-block like
|if (Util.DEBUG)|, where Util.DEBUG is a static boolean variable.

Catching non-thrown exceptions is probably an example of where the
developers made a mistake, in hindsight.
 
M

Mike Schilling

Patricia said:
I don't know the actual reason, but that one does not justify the
choice. The compiler could handle an unreachable catch block in
either
of two ways, leave it in or optimize it out. Both are simple and
straightforward.

In general, Java seems to me to have an inconsistent attitude to
unreachable code. It allows "if(false)" but prohibits sticking in an
early return, leaving unreachable code after it, as well as
prohibiting unreachable catch blocks.

This is explained in the JLS. As a general rule Java forbids
unreachable code. It makes the single exception of "if (false)",
specifically to allow the inclusion of code which can be turned on for
debugging.
 
A

Arne Vajhøj

Patricia said:
I don't know the actual reason, but that one does not justify the
choice. The compiler could handle an unreachable catch block in either
of two ways, leave it in or optimize it out. Both are simple and
straightforward.

Yes.

But the code does not make sense from a production code perspective.

To me it is a very good reason to give error on code that does
not make sense - even though it would be easy to generate code
for it.
In general, Java seems to me to have an inconsistent attitude to
unreachable code. It allows "if(false)" but prohibits sticking in an
early return, leaving unreachable code after it, as well as prohibiting
unreachable catch blocks.

I agree that is inconsistent.

Arne
 
M

Mike Schilling

Patricia said:
Unfortunately, if(false) is not a good general solution to the
temporary code exclusion problem, because the code it excludes has
to
be a compilable statement (including a block statement).

It's still possible to comment out code, but that has the problem that
when you remove the comments, it's quite possible that the code no
longer compiles (or never did.) I find the fact that the syntax is
checked but no bytecode is generated to be a useful feature.
 
B

blue indigo

Well, |if (false)| is not a compile-time error.

What about wrapping the line that throws the exception in if (false)
instead of commenting it out?

If the catch clause is still an error in that case, then it really is
quite perverse.
 
B

Bent C Dalager

What about wrapping the line that throws the exception in if (false)
instead of commenting it out?

If the catch clause is still an error in that case, then it really is
quite perverse.

As I recall, allowing if(false) is more or less an intended idiom to
act as a poor man's #ifdef. That is, you can write
public final static boolean DEBUG = false;
in some central place and then have
if(DEBUG) { /* lots of debug reporting */ }
all over the place that won't make it into the bytecode so long as
DEBUG is false (saving space & cycles).

Or perhaps that is more an evolved consequence of allowing if(false)
then the original intention behind it, that I don't know.

Catching non-thrown exceptions, however, is regarded as just being
sloppy (or more likely confused) and so disallowed since we don't
really want to have software written by sloppy or confused programmers
out there.

Cheers,
Bent D
 
L

Lew

I don't know the actual reason, but that one does not justify the
choice. The compiler could handle an unreachable catch block in either
of two ways, leave it in or optimize it out. Both are simple and
straightforward.

In general, Java seems to me to have an inconsistent attitude to
unreachable code. It allows "if(false)" but prohibits sticking in an
early return, leaving unreachable code after it, as well as prohibiting
unreachable catch blocks.

'if ( false )' was an intentional deviation to allow conditional
compilation, and is explained as such in the JLS:
This approach would be consistent with the treatment of other control structures.
However, in order to allow the if statement to be used conveniently for
"conditional compilation" purposes, the actual rules differ.

It isn't fair to use it as a model for other control structures. They
acknowledge that it's different, they explain why it's different, they
intended it to be different. Complaining then that it's different is
silly.
 
L

Lew

public class Test01
{
    public static void main() {
        try {} catch (java.io.IOException e) {}
    }

}

When I run that, I get the following:

Test01.java:4: exception java.io.IOException is never thrown in body
of corresponding try statement
        try {} catch (java.io.IOException e) {}
               ^
1 error

My question is...  why?  

Because the JLS says so.
 
T

Tom Anderson

public class Test01
{
public static void main() {
try {} catch (java.io.IOException e) {}
}
}

When I run that, I get the following:

Test01.java:4: exception java.io.IOException is never thrown in body
of corresponding try statement
try {} catch (java.io.IOException e) {}
^
1 error

My question is... why? Giving a syntax error over this seems about
as appropriate as giving a syntax error for "if (false)".

As others have said, it's because java won't let you write unreachable
code. The risk would be in cases like:

class FileAccessException extends Exception // *not* an IOException

public void foo() throws FileAccessException { ... }

try {
foo();
}
catch (IOException e) {
// the programmer thinks he'll deal with FileAccessException here,
// but he won't, and that's the kind of thing that leads to bugs
}

Of course, the compiler would still insist on FileAccessException being
handled here, but that's could still get dropped one way or another, once
the programmer's got it in his head that he's dealing with it in that
block.
In both cases, although it may not serve a lot of point in a finished
product, it may be useful for debugging. If I comment out a line that
may (conditionally) throw java.io.IOException, it's annoying having to
comment out a whole slew of other lines, as well. Same thing for "if
(false)". That's easier than commenting out the whole if statement
(especially if there aren't any else's present).

Yes, it's a pain, isn't it. I've been annoyed by this in the past too.
Could you get aikido on java and do something like:

try {
// otherwise empty block
if (false) throw new IOException();
}
catch (IOException e) {
// your catch code here
}

?

tom
 
T

Tom Anderson

Note, though, that this particular check is performed by the compiler
only, whereas the prohibition of "dead code" is generally enforced by
the JVM during bytecode verification(*).

[snip]

That is some very interesting stuff - thanks! I had no idea that the
validator was concerned with dead code - are you saying that it
can/should/must reject bytecode with unreachable instructions?

tom
 
B

blue indigo

As I recall, allowing if(false) is more or less an intended idiom to
act as a poor man's #ifdef.

[rest snipped]

That isn't quite an answer to my question, mate.
 
B

blue indigo

As others have said, it's because java won't let you write unreachable
code. The risk would be in cases like:

class FileAccessException extends Exception // *not* an IOException

public void foo() throws FileAccessException { ... }

try {
foo();
}
catch (IOException e) {
// the programmer thinks he'll deal with FileAccessException here,
// but he won't, and that's the kind of thing that leads to bugs
}

No problem, mate. The compiler will disabuse him of that notion right
quick when it tells him "FileAccessException must be caught, or declared
to be thrown" and points to the "foo()" line.
 
B

blue indigo

Note, though, that this particular check is performed by the compiler
only, whereas the prohibition of "dead code" is generally enforced by
the JVM during bytecode verification(*).
[snip]

Regardless of what the compiler thinks about exceptions, the JVM will
happily accept all of these because transgressions of the "checked
exceptions" rules do not impact the safety of the sandbox model that the
JVM implements.

And transgressions of the "dead code" rules do? How?
 
B

blue indigo

Because the JLS says so.

The quality of your replies seems to me to be highly variable. Sometimes
really useful and informative. Sometimes just a spelling flame or an
apparently-irrelevant rant about top-posting or multi-posting with no
content actually related to the question being asked. Sometimes feeding
the trolls. And sometimes, like now, simply begging the question.
 
A

Arne Vajhøj

Lew said:
'if ( false )' was an intentional deviation to allow conditional
compilation, and is explained as such in the JLS:

It isn't fair to use it as a model for other control structures. They
acknowledge that it's different, they explain why it's different, they
intended it to be different. Complaining then that it's different is
silly.

Not if you are against exceptions to the general rules in the language.

Arne
 
L

Lew

blue said:
The quality of your replies seems to me to be highly variable. Sometimes
really useful and informative. Sometimes just a spelling flame or an
apparently-irrelevant rant about top-posting or multi-posting with no
content actually related to the question being asked. Sometimes feeding
the trolls. And sometimes, like now, simply begging the question.

Thank you for your /ad hominem/ remarks.
 
B

blue indigo

Thank you for your /ad hominem/ remarks.

It was intended as constructive criticism. As, I believe, are some of the
posts you make that I characterized as spelling flames and similarly, but
which maybe could be improved upon, for example by never neglecting the
core point of the preceding post and sometimes by recognizing a lost cause
(such as attempts to educate spammers and trolls).

Perhaps you don't agree.

Carry on, then.
 
M

Mark Space

Mike said:
Patricia Shanahan wrote:

It's still possible to comment out code, but that has the problem that
when you remove the comments, it's quite possible that the code no
longer compiles (or never did.) I find the fact that the syntax is
checked but no bytecode is generated to be a useful feature.


Also, back in the bad old days, commenting out code used to require /*
and */. This was before C++ made the // style of single line comment
popular.

Unfortunately the /* */ failed if one tried to comment out a comment.
So one used #if 0 or similar (#ifdef null). The if(false) construct is
probably a stylistic hold-over from the early C days. This also has an
advantage over // on each line in that it's easier to comment out large
blocks of code. (Think: try doing that with a simple text editor. Ouch.)

Just guessing though, of course.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top