I'd like to see the 'unsigned' property introduced for the primitive
numeric types.
Unsigned byte yes, maybe named "octet" instead of "unsigned byte". The
others no -- too many arithmetic headaches, not enough usefulness when
you have 64-bit signed integers that are good for representing
anything 32-bit or smaller unsigned integers could (so almost any
integer type in C, save "unsigned int" on some uncommon 64-bit-
hardware-specific implementations, and "unsigned long long" in GCC-
specific code).
The other deep but useful changes --
* Make arrays implement List, except for add(). Basically add
.size() (synonymous with .length) and .set() and .get() and
Bob's your uncle.
* Non-nullable references and const. (What's this, linked
elsewhere in this thread? A proposal to add a bunch of
annotations to use with external lint tools? No, no, no!
This should be part of the language and javac. Should have
been from the outset, really. Heck, "const" has been a
reserved word for donkey's years, but unused -- let's use
it! As a part-time C programmer I don't care for Object*
meaning something other than object-pointer, though, so the
non-null symbol should be something else. Hash, maybe, or
caret (^).)
* It would be nice if callbacks had a way to "smuggle" a
checked exception past whatever was calling it to whatever
declared the callback. A quick gloss over this thread shows
that someone else already mentioned something similar, but
it hasn't received much discussion -- as usual, operator
overloading stole the show. As it stands, you can emulate
this by explicitly wrapping the checked exception in a new
RuntimeException and then looking in the calling code for
this exception -- catch RTEs in an inner try, look for and
throw non-null getCause()s, rethrow the RTEs without cause
exceptions, and, with an outer try, catch the desired cause
exceptions. Ugly and verbose but works. A way to automate
this would be nice. I think you can sort of do it if you
are writing both the callback interface and the class that
invokes the callback, as you can use generic parameters as
throws, but this isn't much help if you want to have an
iterator over a structure that lives on disk, say, or a
Comparable that compares things over RMI.
* Actually, the whole notion of checked exceptions, runtime
exceptions, errors, and asserts may be deserving of some
rethinking.
- Checked exceptions: 99% of all checked exceptions are
IOException. Most of the rest are ParseException or
SAXException or something in a similar vein. Perhaps
the exception hierarchy should be Throwable, Error,
Exception, IOException with all unchecked save
IOException, and parsing or other malformed-input
exceptions derived from an InputFormatException that
is a direct IOException subclass.
Rationale: Checked exceptions are supposed to represent
error conditions that arise "in the wild", without
requiring a program bug to occur. Ergo, they represent
not errors in the program but errors in its input or
errors in its output. Ergo, they are all IOExceptions,
albeit sometimes in disguise.
- Runtime exceptions, errors, and asserts: these divide
up into four categories, but not exactly corresponding
to the above.
o Validation of preconditions, postconditions, and
invariants, for bug-detection, in custom code.
Typically IllegalArgumentException,
IllegalStateException, and friends get used in
precondition checking, and asserts and Errors in
the other cases. These are probably best off all
changed to asserts, but with precondition
asserts (those that appear before any other code in
a method body) perhaps being always-on and throwing
IAE (ISE if they don't reference any method
parameters) to emulate the older way. OTOH, I don't
see that precondition checks are any less or more
valuable to have enabled in production code. The
main objection to asserts is that no-one turns them
on. IDEs should turn on asserts for all code launched
from the IDE by default, and assert failures should
be trapped like breakpoints whenever a debugger is
attached.
o Safety-net validation of crucual system invariants,
preconditions, and postconditions. This is where we
get VMError, assorted other Errors, primitive-op
ArithmeticException (mainly div by zero), and non-
explicit throws of NullPointerException.
Non-nullable references would go a long way toward
helping with the latter, especially if the syntax
was not too verbose and stock javac and built-in IDE
compilers/linters caught errors in their use.
Better asserts would help too. Programmers should
be encouraged in the meantime to catch nulls when they
first go into anything they shouldn't go into, using
asserts or explicit throws (preferably of
IllegalArgumentException, since if null is an illegal
argument, it's an illegal argument error). And if
the distinction between RuntimeException and Error is
supposed to be that the latter indicates a VM failure
or other critical system problem rather than a coding
bug, then AssertionError should become
AssertionException, and that also brings us to:
o Out of memory/stack. OOME and StackOverflowError
are sort of in-between, hard to recover from but
usually indicative of a program bug, especially in
the latter case. OOME should be easier to cope with,
somehow. Don't ask me how. I think there was
discussion of that elsewhere in this thread.
o Non-local return. Perhaps it's time to make another
presently-unused reserved word useful: the dreaded
and much-maligned "goto". But with a limitation: it
can only target a label reached by a simple stack
unwind, i.e. stand in for a throw/catch of a new
RuntimeException/Error class. So you could have
int foo = bar;
quux = baz.twitchAndShout();
myLabel: fiddlesticks();
q = rx * 17;
and in something called by fiddlesticks,
if (x) goto myLabel;
with a runtime exception if there's no myLabel in
the call stack. Actual implementation being to
throw an "efficient" MyLabelRuntimeException
at the "goto" and catch it at myLabel. Here
"efficient" means "don't generate the stack
trace, unless running with a debugger attached,
and don't really have a whole new class loaded
for each label, instead parametrize the exception
and have the catch, match, and rethrow-on-no-match.".
OK -- now I've mentioned "goto" you need no further excuse to flame
the crap out of me. But you were probably going to do that anyway, so
I thought, what the hey.