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

G

Guest

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

It is not very likely that you can get the app up and working again.

It is difficult to recover when you can not allocate more memory.

Most experts recommend not to attempt to do so.

But Java is not preventing you from trying if you insist.
How do you know, when implementing a library, whether I will want to
catch and handle a certain error condition?

The point is that exception is part of the contract exposed by the
library.

It does not make more sense to want to change exception
types than to change the argument and return types.

Arne
 
L

Lew

Arthur said:
[Xpost to c.l.j.help removed.]

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

Generics. Templates are what C++ has.

That is what I was talking about. The List usually will not store Objects, but
the subclass.

List< MyClass > list = new ArrayList< MyClass > ();
// fill the list
MyClass instance = list.get(2);

// more usually, not direct access but iterated
for ( MyClass instance : list )
{
instance.doSomething();
}

No downcast necessary.

The compile-time safety comes from the mandatory type declaration. The Jython
example is equivalent to List< Object >, or perhaps List< ? >. If it's like
other such languages, the Jython reference can hold lists of arbitrary type as
the need arises.

In Java you make the List <Object>, <?> or <Foo>, etc., as needed. That gives
the benefit of static type checking.

Java syntax is more verbose and precise. Useful when such attributes are
wanted. Jython is better for more fluid styles.

I use JSP EL a lot. It is loose, similar to your Jython example. In that
context such looseness and compactness is very useful.

For the underlying Java classes I use exception handling, immutable types,
yada best practice blah blah - all that stuffy stuff really helps.

Each language resonates to a mindset. Is a saw better than a screwdriver?

- Lew
 
L

Lew

Robbert said:
True. By the way, are people who don't speak French supposed to
understand that last sentence?

It's a pretty common cliché in English, too. I guess there is a feeling of
savoir faire in using Francophone expressions. It lends a certain cachet,
n'est-ce pas?

English is filled with French expressions. You might say that borrowed words
and phrases are part of the raison d'être for the language.

<http://home.tiac.net/~cri_c/editorials/edit074.html>

"The following has been attributed to James Nicoll:

" English doesn't so much 'borrow' words from other languages; it chase
other languages down dark alleyways, knocks them over the head and rifles
through their coat pockets for new words."

- Lew
 
A

Arthur J. O'Dwyer

It is not very likely that you can get the app up and working again.

It is difficult to recover when you can not allocate more memory.

Most experts recommend not to attempt to do so.

Hah! Please don't post ridiculous misinformation; it just confirms
my prejudices against Java programmers. <half-winky/> If you are
writing any kind of robust software, you *need* to make it robust
against out-of-memory conditions. Sure, the most obvious and practical
way to do that is usually to make it monopolize the processor, and not
let any other tasks run while it's running (e.g., a lot of embedded
software, or an operating system that assumes the first 0x100000 bytes
of RAM is totally reserved for its own use). But sometimes you're
writing software for multi-user or multi-task systems --- for example,
a Web server, or a Web browser, or a BitTorrent client, or a video
player, or a PDF viewer, or a word processor, or an IDE, or an image
editor, or... okay, I'm out of icons on my desktop now.[1]

In those cases, you *need* to do something sensible when the OS
decides you've had enough memory. Even popping up a dialog box with
a snarky haiku and then crashing the system is doing *something*,
and therefore requires code somewhere to be executed when an exception
is raised.
The point is that exception is part of the contract exposed by the
library.

It does not make more sense to want to change exception
types than to change the argument and return types.

I am starting to think that you are deliberately misinterpreting
Robert's words.

my $.02,
-Arthur

[1] - No, I don't have a Web server icon on my desktop. ;) But it was
easy to free-associate from "server" to "browser", instead of spending
time looking up all the other Unix daemons and utilities that might
need memory. (But I can! FTP server, SSH server, SSH client, shell,
printer daemon, anything security-related,...)
 
R

Robbert Haarman

That it can throw an exception.

Just because it doesn't have to be typed in by programmers doesn't mean
it's hidden from them. Just like types are inferred and can be displayed
in languages like OCaml, inferred exceptions could be displayed, as
well.

Specifically, what I had in mind in case of Java was the list of
exceptinos that a method can throw being listed in the generated (by
javadoc) documentation.
And the same can be the case for abstract classes.
Yes.

I like the consistency in the choice Java made.

Makes sense.

Regards,

Bob
 
L

Lew

Robbert said:
Specifically, what I had in mind in case of Java was the list of
exceptinos that a method can throw being listed in the generated (by
javadoc) documentation.

Just like now.

Of course, that doesn't save you any typing, because you have to type in
Javadoc comments, so you'd have to type the throws list into your Javadoc
comments anyway.

Might as well have it in the code, thus avoiding the whole-program-analysis,
dynamic-link issue, and copy-past it into your Javadocs.

- Lew
 
R

Robbert Haarman

Just like now.
Yes.

Of course, that doesn't save you any typing, because you have to type in
Javadoc comments, so you'd have to type the throws list into your Javadoc
comments anyway.

I don't know why you think that. The compiler can infer the exceptions
that methods may throw, and those can be put in the generated
documentation, without the programmer having to type in anything.
Might as well have it in the code, thus avoiding the
whole-program-analysis, dynamic-link issue, and copy-past it into your
Javadocs.

I'd rather have the compiler working for me than myself working for the
compiler.

Regards,

Bob
 
L

Lew

Robbert said:
I don't know why you think that. The compiler can infer the exceptions
that methods may throw, and those can be put in the generated
documentation, without the programmer having to type in anything.

I think that because Javadocs are written by hand, not auto-generated by the
Java system.

- Lew
 
R

Robbert Haarman

I think that because Javadocs are written by hand, not auto-generated by
the Java system.

Oh, come on. Plenty of things are already automagically added to
Javadocs. And even if that weren't the case, there is nothing preventing
throwable exceptions to be automatically generated.

Regards,

Bob
 
T

Tor Iver Wilhelmsen

PÃ¥ Thu, 22 Feb 2007 16:16:24 +0100, skrev Robbert Haarman
Oh, come on. Plenty of things are already automagically added to
Javadocs.

.... by IDEs. Do you want Java development to be entirely IDE-dependent
like Visual Basic is?
And even if that weren't the case, there is nothing preventing
throwable exceptions to be automatically generated.

So: When the world is moving AWAY form the "hack" that XDoclet represents,
you want to move back to it? Exceptions are ingrained into
Java-the-language, moreso than other things XDoclet was used for, like
Hibernate and EJB bindings.

"throws" is not going away more than e.g. method return types or
parametrized types are. Because they are useful. Simply because
compile-time checks beat runtime checks any day.
 
L

Lew

skrev Robbert Haarman :
... by IDEs. Do you want Java development to be entirely IDE-dependent
like Visual Basic is?

Javadocs are written by hand. Like many manual tasks, there exist third-party
tools (like Eclipse and NetBeans) that help with the process, but nothing in
Java /per se/ automates Javadoc content.

So, to answer Robert's question more precisely, I think that having to write
throws information in Javadocs is not automatic because nothing in Javadoc
content is automatic, unless you use a third-party tool, which moots the
conversation about what Java supports.

- Lew
 
C

Chris Smith

Tor Iver Wilhelmsen said:
... by IDEs. Do you want Java development to be entirely IDE-dependent
like Visual Basic is?

I think you misunderstand. Lots of things really are added to the
JavaDoc that are not part of the /** comment in the source. If
exception lists were inferred (which seems like a good idea in many
cases), there's no reason they wouldn't be added to JavaDoc in the same
manner as the method name, access specifier, etc. The information would
not be directly available in the syntax of the source code, so it would
complicate the implementation... but that isn't really anything
fundamentally new. JavaDoc already plays compiler in many other ways.
So: When the world is moving AWAY form the "hack" that XDoclet represents,
you want to move back to it?

What exactly is your understanding of the hack that XDoclet represents?

I am quite sympathetic to the view that checked exceptions are a helpful
language feature. I am considerably less sympathetic to the view that
inference of checked exceptions is always a bad idea.
 
L

Lew

Chris said:
I think you misunderstand. Lots of things really are added to the
JavaDoc that are not part of the /** comment in the source. If

That is simply not true, at least with respect to Java. Yes, third-party tools
can add some content to Javadoc comments, but the discussion in this thread
has been what Java can or should do. Javadoc comments are written by hand.

The Javadoc tool can do things like expand package names of classes, but only
for those classes that are manually mentioned in the Javadoc comments.

- Lew
 
C

Chris Smith

Lew said:
That is simply not true, at least with respect to Java. Yes, third-party tools
can add some content to Javadoc comments, but the discussion in this thread
has been what Java can or should do. Javadoc comments are written by hand.

There's some kind of miscommunication going on. For example, JavaDocs
contain the names and access specifiers of method. Those names and
access specifiers are not generally put into the /** comments in the
source code. They are read by JavaDoc parsing the source code, thus
acting at least a little like a compiler.
 
C

Chris Smith

In retrospect, a better example might be that JavaDoc generates, for
each class, a list of all the other classes or methods that use a given
class. This is a non-trivial amount of work, which involves a global
scan of all the source code being documented. This is not much
different at all from what would be needed to infer exceptions.
 
J

James Harris

....
- 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 list is very helpful. I wonder that the Java programming texts I
have read don't explain this clearly. They do explain that subclasses
of RuntimeException (and Error) are unchecked but little seems to be
built under RuntimeException.
From a language design perspective (not talking Java here and please
forgive the anthropomorphising of modules) perhaps there is a natural
tension between the needs of the module: what exceptions it wants or,
perhaps for some reason it 'requires' the immediate caller to handle,
and the needs of the caller which may want to choose whether to handle
all or some called-module exceptions itself..... Just thinking about
this, I can't actually think of one reason (doubtless someone else
will) why I would want to insist my direct caller in some way deals
with the exceptions that I might throw. I /would/ see value in making
clear what exceptions I might throw so that the compiler can check
that /some/ method higher up the calling chain handles them. If I am a
caller of a module I would rather have the choice of which exceptions
I want to handle myself. I would certainly like to /know/ what my
called modules may throw so that I could choose which ones to handle.
I may even want to insist that I not compile unless I have dealt with
all possible exception conditions but that is my choice. I would not
want to be /prevented/ from compiling by a callee unless that was my
choice.

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

I agree. As a language /user/ it is not a big issue. It may add bloat
my code a little with issues that are secondary (to me) but that is
just one of those things. If I am using a language I might complain
about certain aspects but I just have to get on with it. If it gets
done the job I want it to I am happy.

As a language designer this does become important. Programmers who
will use a language are effectively customers. The language designer
is the supplier. To stay in business the supplier needs to fill the
needs of his customers and take on board their preferences. Therefore
if they complain about a feature of it he needs to understand why and
respond. Don't take crisicisms of Java to heart. They more accurately
reflect a search for a better way.
 
L

Lew

Chris said:
There's some kind of miscommunication going on. For example, JavaDocs
contain the names and access specifiers of method. ....
In retrospect, a better example might be that JavaDoc generates, for
each class, a list of all the other classes or methods that use a given
class. This is a non-trivial amount of work, which involves a global
scan of all the source code being documented.

I see what you mean, but that is not "automagically" generated, that is
content that came from what the programmer manually put in.

At best, your argument supports eliminating the Javadoc @throws tag and
picking the information up from the method signature's throws clause.

First, that would makes the method's actual throws clause even /more/
necessary, since you would no longer have the @throws tag available.

Second, it puts us right back to what I was saying, that all Javadoc content
must be entered manually by the programmer. Some of that information comes
from the /** comments and some from Java source itself, but none of it comes
from .class files or anything but what the programmer manually entered.
(Modulo exogenous tools.) That is my main point, not whether the manually
entered information is in the /** comment or some other part of the source
artifacts.

- Lew
 
R

Robbert Haarman

PÃ¥ Thu, 22 Feb 2007 16:16:24 +0100, skrev Robbert Haarman


... by IDEs. Do you want Java development to be entirely IDE-dependent
like Visual Basic is?

No, please, no. That's the last thing I want. I was merely saying that
not forcing the programmer to write information in the source code does
not mean the information is not available.
So: When the world is moving AWAY form the "hack" that XDoclet represents,
you want to move back to it? Exceptions are ingrained into
Java-the-language, moreso than other things XDoclet was used for, like
Hibernate and EJB bindings.

Sorry, I am not following you. What is XDoclet?
"throws" is not going away more than e.g. method return types or
parametrized types are. Because they are useful. Simply because
compile-time checks beat runtime checks any day.

I'm getting tired of this. You guys keep assuming that compile time
checks are only possible with annotations in the source code. That is
simply not true. Take a look at OCaml or Haskell someday. No type
annotations (except in type classes and the like), and yet, it performs
type checking at compile time, and it can tell you which types the
arguments and return values should have. The same could work for
exceptions, too.

Regards,

Bob
 
R

Robbert Haarman

I see what you mean, but that is not "automagically" generated, that is
content that came from what the programmer manually put in.

Of course, I wasn't claiming that the information comes from nowhere. Of
course, it comes from something some programmer entered. All I meant is
that it can be deduced from throw statements, and that the throws clause
is, thus, redundant.

Regards,

Bob
 
J

James Harris

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

Hmm, I don't know. Wrapping up one exception type in another seems to
me to be verging on the kludge particularly if the /reason/ for
wrapping it up is to pass it up the calling chain silently and thus
avoid an inbuilt mechanism of the language. I completely agree with
the principle of information hiding - Parnas' principles and all that.
I'm not convinced the analogy is *exactly* apt. Maybe the converse.
Checked exceptions seem like the employee record forcing any code that
reads it to examine all fields whether they are relevant to its
purpose or not.
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.

Fair enough. I can see the value of this in development and, you may
be surprised to know, I like this feature. If I can declare exceptions
that will be generatable later I can build the checking now and come
back to actually throwing the exceptions and testing later. Good! I
still want to handle them where appropriate, though, not necessarily
having to include code for them at the lowest level. If the compiler
could warn me of any declared but not yet throwable exception so much
the better. It would be a good reminder that work is required.
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.

I think you misunderstand me. I wasn't saying that one should catch
Exception but that it is reasonable to accept that arbitrary things
can go wrong in any called module. Java's mechanism is, at best,
partial.
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.

What if the requirement was that checked exceptions had to be handled
just "somewhere above" the called module, if nowhere else, then in
main (for an application)? This ensures the compiled code handles all
declared generatable exceptions.
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.

How about simply allowing the catching to be done higher up?
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?

I think the comment of mine that you snipped was a valid example! If
I'm wrong and you didn't snip it the example I was thinking of was
Pascal's treatment of array dimensions as part of the array type. Type
safety gone too far. As another example, say I define a complicated
function to work on two integers and return a third. I really don't
want to write separate functions: one for bytes, one for 16-bit
values, one for 32-bit and one for 64-bit. I want to define just one
for integers and then perhaps state the types for which it applies.
Now, how many pieces of machine code does that need? If I am not
needing to check for overflow etc I may allow anything less than the
word size of the host machine to be handled as words. For example, on
a 32-bit machine, from the same single piece of source code I may
generate executable code for just two types: 32-bit integers and 64-
bit integers. It (the 32-bit version) can still run on integers of 8
or 16 bits as long as the returned value is taken from the lower bits
of the result. Thus I want the control of selecting arguments based
on /partial/ type information.

Your question about my criteria for selecting static validation
features is a good one. I don't have a complete picture yet. I am
planning to allow the programmer the choice in more areas than are
traditional in programming languages. I don't really want to go too
far off topic on this as some things are a discussion in themselves
but to pick one example: Languages generally mandate either structural
equivalence of types or name equivalence. Once decided by the language
creator the decision is fixed; this is a very early binding time. I
wonder if there is some way the programmer could simply specify which
types are compatible and it what ways. The type safety is still there
and the programmer has the control needed. Taking it away from this
specific example and back to the general I don't want to mandate too
many static validation features aritrarily but I still want to make
them available so they can be used by the programmer if needed. I see
the programmer as a customer, here, and the language as a product,
with all the balancing acts that requires. In practice there would be
another customer: the programmer's employer (or supervisor or
customer, as appropriate). The employer may have coding standards in
to which the produced code is expected to fit. Therefore coding
standards would be enforceable and could be used to restrict certain
options. In this way the flexibility is allowed where needed but
bounds may be set.
 

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

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top