Exception Names

R

Roedy Green

It may be too late now, but it would be nice if some exceptions were
renamed and the old names deprecated.

NullPointerException : We Javites make such a production of the fact
Java has no pointers, just references. This should be called
NullReferenceException.

IllegalArgumentException: there is nothing illegal involved. This
should be renamed InvalidArgumentException.

There needs to be some exceptions much like IllegalArgumentException
that make a finer distinction.

InvalidDataError : Somebody goofed preparing the data.
CorruptDataError : checksums bad, wrong data format.
ProgrammingError : something that should not be possible, similar to a
failed assertion that is not turned off.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Don’t worry about the world coming to an end today.
It is already tomorrow in Australia."
~ Charles Schulz
 
T

Tom Anderson

It may be too late now, but it would be nice if some exceptions were
renamed and the old names deprecated.

NullPointerException : We Javites make such a production of the fact
Java has no pointers, just references. This should be called
NullReferenceException.

Or references should be renamed to pointers. After all, java's references
are much more like C pointers, which are (usually) pointers to objects,
than C++ references, which are pointers to variables. Even Smalltalk calls
them pointers rather than references.
IllegalArgumentException: there is nothing illegal involved. This
should be renamed InvalidArgumentException.

There needs to be some exceptions much like IllegalArgumentException
that make a finer distinction.

InvalidDataError : Somebody goofed preparing the data.
CorruptDataError : checksums bad, wrong data format.
ProgrammingError : something that should not be possible, similar to a
failed assertion that is not turned off.

If we're reforming exceptions:

MalformedURLException should *require* the malformed URL as a parameter,
and include it in its toString. I had a MalformedURLException emerging
from deep within the guts of my app server recently, and had no bloody
clue what was going wrong, because neither the exception nor the logs
indicated what the URL in question was!

InputStream.read should throw an EOFException instead of returning -1 at
the end of a stream. Checking return values for special values is goofy C
bullshit that we shouldn't be doing in the 21st century. Personally, i'd
also like to see Map.get throw a KeyNotFoundException or some such instead
of returning null when a key isn't in the map, but i think most people
wouldn't agree with me on that.

I can probably think of loads more ...

tom
 
S

Stefan Ram

Roedy Green said:
NullPointerException : We Javites make such a production of the fact
Java has no pointers, just references. This should be called
NullReferenceException.

»(...) reference values (...) are pointers«

JLS3, 4.3.1.

http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1
IllegalArgumentException: there is nothing illegal involved.
This should be renamed InvalidArgumentException.

»illegal (...) Not permitted by rules«

http://en.wiktionary.org/wiki/Illegal
 
B

Bent C Dalager

Personally, i'd
also like to see Map.get throw a KeyNotFoundException or some such instead
of returning null when a key isn't in the map, but i think most people
wouldn't agree with me on that.

This seems very situational. In some use cases, a Map receiving
lookups of entries it doesn't have is considered entirely normal (a
cache perhaps) and so shouldn't be handled as an exception (and having
to first do a boolean lookup of the type "isEntryPresent" only then to
call get() on the same entry seems wasteful) and a null return value
is both useful and proper. In other uses you only look up values you
know should be there and in these cases a miss should be handled as an
exceptional condition.

The distinction can be handled by having different Map classes for the
different use cases, by having a state the Map can be put in (do/do
not throw on miss) at creation or even dynamically, or by having a
wrapper layer that changes the default (currently "return null on
miss") to whatever you desire. The latter is probably the easier to
introduce retroactively although it may have to throw an unchecked
exception.

I don't see that either behaviour is "naturally" more correct than the
other across all use cases however. The default should probably be
chosen based on how easy it is for a wrapper to painlessly convert it
into the other behaviour.

Cheers,
Bent D
 
L

Lew

rossum said:
It may bee goofy but it is very likely to be a whole lot faster.
Throwing and catching an exception is probably going to be a lot
slower than checking the return value.

Besides, there's nothing exceptional about reaching the end of a stream. One
would venture to say that one nearly always reaches the end of a stream,
*unless* something exceptional happens.
 
L

Lew

Roedy said:
It may be too late now, but it would be nice if some exceptions were
renamed and the old names deprecated.

NullPointerException : We Javites make such a production of the fact [sic]
Java has no pointers, just references. This should be called
NullReferenceException.

What's this "we" shite? Java does, too, have pointers. Stefan Ram even
quoted where the JLS says so.

People who "make such a production of the [non-]fact [that] Java has no
pointers" are sadly misguided. Anyone who really knows Java knows otherwise.
 
R

Roedy Green

What's this "we" shite? Java does, too, have pointers. Stefan Ram even
quoted where the JLS says so.

People who "make such a production of the [non-]fact [that] Java has no
pointers" are sadly misguided. Anyone who really knows Java knows otherwise.

Sun may be coming round to your point of view, but before your time
they strenuously wanted to distance themselves from the dangers of
C/C++ "wild" pointers.

e.g.

http://java.sun.com/docs/white/langenv/Simple.doc2.html

Most studies agree that pointers are one of the primary features that
enable programmers to inject bugs into their code. Given that
structures are gone, and arrays and strings are objects, the need for
pointers to these constructs goes away. Thus, Java has no pointer data
types. Any task that would require arrays, structures, and pointers in
C can be more easily and reliably performed by declaring objects and
arrays of objects. Instead of complex pointer manipulation on array
pointers, you access arrays by their arithmetic indices. The Java
run-time system checks all array indexing to ensure indices are within
the bounds of the array.

You no longer have dangling pointers and trashing of memory because of
incorrect pointers, because there are no pointers in Java.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Don’t worry about the world coming to an end today.
It is already tomorrow in Australia."
~ Charles Schulz
 
M

Mike Schilling

Tom said:
Or references should be renamed to pointers. After all, java's
references are much more like C pointers, which are (usually)
pointers to objects, than C++ references, which are pointers to
variables. Even Smalltalk calls them pointers rather than
references.

Java "references" are exactly like Pascal pointers in that they point
only to dynamically created objects and that the only operation on
them is "dereference"; there's no notion of pointer arithmetic.
 
M

Mike Schilling

Lew said:
Besides, there's nothing exceptional about reaching the end of a
stream. One would venture to say that one nearly always reaches the
end of a stream, *unless* something exceptional happens.

Right; the most Java-ish thing would be for Streams to be
iterator-like:

while (stream.hasNext())
{
char c = stream.next();
}

or even

for (char c: stream)
{
}
 
A

Arved Sandstrom

Lew said:
Roedy said:
It may be too late now, but it would be nice if some exceptions were
renamed and the old names deprecated.
NullPointerException : We Javites make such a production of the fact
[sic]
Java has no pointers, just references. This should be called
NullReferenceException.

What's this "we" shite? Java does, too, have pointers. Stefan Ram even
quoted where the JLS says so.

People who "make such a production of the [non-]fact [that] Java has no
pointers" are sadly misguided. Anyone who really knows Java knows
otherwise.
The JLS specifically says:

"The reference values (often just references) are pointers to these
objects, and a special null reference, which refers to no object."

We already know that in many JVM implementations the reference value is
a pointer to a pointer (a handle), not a pointer to the object instance,
so the JLS is misleading. As far as I am aware, some native methods in
JDKs did or do even assume that handles are how a JVM will implement
references, which means that a JVM that does things differently must
take this assumption into account.

However, no argument from me that a Java reference is a pointer,
regardless of what it's pointing at.

AHS
 
O

Owen Jacobson

Right; the most Java-ish thing would be for Streams to be
iterator-like:

while (stream.hasNext())
{
char c = stream.next();
}

or even

for (char c: stream)
{
}

Writing a StreamIterable adapter is fraught with annoying, though.
Consider: both .next() and .hasNext() *potentially* perform IO,
depending on whether you've already called hasNext when calling next.
And you can't throw any checked exceptions.

Grr.

-o
 
M

Mike Schilling

Owen said:
Writing a StreamIterable adapter is fraught with annoying, though.
Consider: both .next() and .hasNext() *potentially* perform IO,
depending on whether you've already called hasNext when calling next.
And you can't throw any checked exceptions.

It's no worse than, say, creating a Collection backed by a disk file or
database. You have to wrap the exceptions with RuntimeExceptions. What I'm
not seeing a way around is being able to return a char rather than having to
wrap them as Characters. I suppose you could create a CharacterHolder that
isn't immutable and return the same instance with different contents each
time, but that seems cheesy.
 
M

Mike Schilling

Lew said:
Roedy said:
It may be too late now, but it would be nice if some exceptions were
renamed and the old names deprecated.

NullPointerException : We Javites make such a production of the
fact [sic] Java has no pointers, just references. This should be
called NullReferenceException.

What's this "we" shite? Java does, too, have pointers. Stefan Ram
even quoted where the JLS says so.

People who "make such a production of the [non-]fact [that] Java has
no pointers" are sadly misguided.

The pointer vs. reference wank began as a story Sun told to support the idea
tht Java is much simpler than C++. Java pointers are much simpler than C++
pointers, of course: arrays names don't "decay" into them, there's no
arithmetic on them, they can't become invalid when something gets freed,
etc. To emphasize these difference, Sun used a different word for them.
 
T

Tom Anderson

It may bee goofy but it is very likely to be a whole lot faster.
Throwing and catching an exception is probably going to be a lot slower
than checking the return value.

I don't believe it for a second, and even if it is true, it's not a good
enough reason.

tom
 
T

Tom Anderson

Besides, there's nothing exceptional about reaching the end of a stream.
One would venture to say that one nearly always reaches the end of a
stream, *unless* something exceptional happens.

There's something entirely exceptional about asking an object for
something (a next byte) that it can't give you. If a method can't do what
you've asked it to do, it should throw an exception.

tom
 
T

Tom Anderson

Right; the most Java-ish thing would be for Streams to be
iterator-like:

while (stream.hasNext())
{
char c = stream.next();
}

or even

for (char c: stream)
{
}

Is this a good time to mention that in python, iterators don't have a
hasNext method, and instead their next method just throws StopIteration
at the end? :)

tom
 
T

Tom Anderson

This seems very situational. In some use cases, a Map receiving lookups
of entries it doesn't have is considered entirely normal (a cache
perhaps) and so shouldn't be handled as an exception (and having to
first do a boolean lookup of the type "isEntryPresent" only then to call
get() on the same entry seems wasteful) and a null return value is both
useful and proper. In other uses you only look up values you know should
be there and in these cases a miss should be handled as an exceptional
condition.

I certainly agree that both these use cases are valid (although i'd bet
the latter is ten times more common), but i don't see why having a null
return is necessary to address the former. This code:

Thing value = map.get(key);
if (value != null) {
dealWithValue(value);
}
else {
dealWithLackOfValue();
}

Is trivially rewritten as:

try {
Thing value = map.get(key);
dealWithValue(value);
}
catch (KeyException e) {
dealWithLackOfValue();
}

With no loss of readability. There is a potential performance penalty, but
i don't believe it would be significant with modern VMs.

Many people will dislike the latter version because it 'abuses'
exceptions. I think this betrays an overly dogmatic attitude to
exceptions, but it's a matter of taste.

The thing that most motivates me to want the latter version is that it
makes it impossible to ignore absent keys. With a null return, code like
this:

class Customer {
private static Map<Locale, Country> COUNTRIES_BY_LOCALE;

private Country country;

public Customer(Locale locale) {
country = COUNTRIES_BY_LOCALE.get(locale);
}
}

Effectively fails silently; when there is no country for that locale in
the map, the customer gets a null country, and the code continues. Later,
at some distant point in the code, things go tits-up because of that null
country. Yes, you could add a null check in the constructor, but that's an
extra line of code that has to be remembered to be written. Because
Map.get fails silently, it has to be written *every* time that method is
called! If Map.get threw an exception on a missing key, it would be much
harder to ignore - it would take active work to write a catch-and-ignore.
The distinction can be handled by having different Map classes for the
different use cases, by having a state the Map can be put in (do/do not
throw on miss) at creation or even dynamically,

Horrible!

The Right Thing to do would be to have two methods, get (which throws an
exception) and getIfPresent (which returns null). Or get(K), and get(K,
V), where the second version takes a default value to return if the key
isn't in the map - often much more useful than a null return. Of course,
this is a change which would be impossible to retrofit, because it would
break existing code - this would have to have been done when Map was first
written. But then, any change to the semantics of Map.get at this point
falls foul of the same trap.
or by having a wrapper layer that changes the default (currently "return
null on miss") to whatever you desire. The latter is probably the easier
to introduce retroactively although it may have to throw an unchecked
exception.

That's a good idea - it would be another Collections.somethingMap method.
The wrapper would probably have to disallow null values in order to work
efficiently. And you could have a Collections.defaultingMap which does the
return-a-default thing, althought the default would be fixed per instance
rather than per call.
I don't see that either behaviour is "naturally" more correct than the
other across all use cases however.

That's true. I'd rather have both than either one, for sure.
The default should probably be chosen based on how easy it is for a
wrapper to painlessly convert it into the other behaviour.

It's not possible to convert the current behaviour to what i want unless
you know that there are no null values in the map. Not without calling
containsKey every time, anyway.

tom
 
T

Tom Anderson

There are two kinds of conceptual "read" operations on a stream. One is
some kind of "get me the next byte(s), or end-of-stream, whichever comes
first". The other is more on the lines of "get me the next byte, which
had better be present, because it is expected, and early EOF is an
error". A single read() method cannot implement both semantics
simultaneously.

I'm going to repeat what i said about maps, and point out that:

int nextByte = in.read();
if (nextByte != -1) {
handleByte(nextByte);
}
else {
handleEnd();
}

Can trivially be rewritten as:

try {
int nextByte = in.read();
handleByte(nextByte);
}
catch(EOFException e) {
handleEnd();
}

Or another common idiom:

int nextByte = in.read();
if (nextByte == -1) {
handleEnd();
return
}
handleNextByte(nextByte);

try {
int nextByte = in.read();
handleNextByte(nextByte);
}
catch (EOFException e) {
handleEnd();
return;
}
Sun could possibly add some readFully() methods to InputStream, such
as:

public int readFully()
throws IOException
{
int x = read();
if (x < 0)
throw new EOFException();
return x;
}

public void readFully(byte[] buf)
throws IOException
{
readFully(buf, 0, buf.length);
}

public void readFully(byte[] buf, int off, int len)
throws IOException
{
while (len > 0) {
int rlen = read(buf, off, len);
if (rlen < 0)
throw new EOFException();
off += rlen;
len -= rlen;
}
}

but with some extra thinking about what should be done with
multi-threaded access, and possibly some prior checks on provided array
offsets and lengths.

These methods are already in DataInput(Stream):

http://java.sun.com/javase/6/docs/api/java/io/DataInput.html#readByte()
http://java.sun.com/javase/6/docs/api/java/io/DataInput.html#readFully(byte[])
http://java.sun.com/javase/6/docs/api/java/io/DataInput.html#readFully(byte[], int, int)

So i suppose that if i had a burning desire for them, i could just wrap my
stream in a DataInputStream.
However, it is somewhat delicate to add such methods to InputStream
because there are many projects out there which extend InputStream and
may have added methods named readFully(). Source-code compatibility may
be altered.

Oh yes - it's definitely far too late to add these methods to existing
classes. I'm just moaning about them not being there from the start.

tom
 
L

Lew

Tom said:
Later, at some distant point in the code, things go tits-up because of
that null country. Yes, you could add a null check in the constructor,
but that's an extra line of code that has to be remembered to be written.

It still has to be written, although your general discussion of the use case
for exceptions is cogent.

It's a question of invariants, and the notion that a class is written once and
used many times.

If a class design requires that an attribute be not 'null', that is
algorithmically an invariant. Exceptions enforce that invariant. The first
correct place to put such an exception, presumably a runtime exception, is in
the constructor. That way the rest of the code can be written with neither a
'null' check nor an access-time exception.

Invariants can be asserted.

public class Customer
{
private static final Map <Locale, Country> COUNTRIES_BY_LOCALE;
static
{
COUNTRIES_BY_LOCALE = buildCountries();
}
static Map <Locale, Country> buildCountries()
{
Map <Locale, Country> rv = new HashMap <Locale, Country> ();
...
return Collections.unmodifiableMap( rv );
}

private final Country country;

public Customer( Locale locale )
{
this.country = COUNTRIES_BY_LOCALE.get( locale );
if ( this.country == null )
{
throw new IllegalStateException(
new NullPointerException(
"No country for "+ locale.getDisplayName()"
));
}
assert this.country != null; // postcondition
}

public final Country getCountry()
{
assert this.country != null; // precondition
return this.country; // no exception necessary
}
}
 
M

Mike Schilling

Tom said:
Is this a good time to mention that in python, iterators don't have
a
hasNext method, and instead their next method just throws
StopIteration at the end? :)

Really? That's awful.
 

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,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top