Could you elaborate that in more depth please? What's so bad about it in
your opinion?
To the first question: Original C had no `void' type at all.
When you had a function (Java: "method") that returned nothing,
it was actually written as if it returned `int'. The caller was
supposed to ignore whatever garbage happened to land in the
"function value goes here" place (often a designated CPU register),
and that was that.
Since the compiler couldn't tell a sort-of-`int' function
from a really-`int' function, it had to permit calls to either
kind as the second and third operand of the ?: operator -- since
the two kinds were entirely equivalent, there was no way to forbid
the former while allowing the latter. Some C programmers found
they could use ?: as a sort of "one-line if/then/else", and did
so. The condensation was occasionally useful in macro expansions,
and besides: We old-line C programmers value terseness above all
else, even speed (and we value both above correctness
.
Along came ANSI C, bearing `void' along with other gifts,
and it became possible to distinguish the two kinds of function.
The compiler could squawk if a non-`void' function failed to
return a value, or if a caller tried to use the non-existent
value of a `void' function. It would also have been possible
to forbid `void' operands for ?:, but one of the Committee's
charges was to invalidate as little existing code as possible.
So they "grandfathered" existing practice by making a special
case: the second and third operands could be compatible types,
or they could both be `void'. (I think this makes ?: one of
only two C operators that can take a `void' operand, the other
being the , operator.)
So: The "historical accident" is that `void' was a latecomer,
and the rules were warped to preserve the investment in old code.
To your second question, I don't think it's as "bad" as all
that, but neither do I think allowing `void' operands is "good."
In Java we can say that all operators take actual values as
their operands and yield actual values as their results, and the
ability to say "all" instead of "all except" seems to me a sign
of cleanliness in the language. (Note that `new' is not an
operator, but a keyword introducing a "class instance creation
expression," JLS 15.9. Even [] and (type), which seem very
operator-like to me, are not called "operators" in JLS.)
Also, it appears that `void' is not a "type" in Java. That
may be a controversial position (i.e., I may have to eat my
words), but note that `void' is not listed as a type anywhere
in JLS 4. The description of java.lang.Void says it's a place-
holder for "the Java *keyword* [emphasis mine] void," not for
a type. So `void' has an entirely different status in Java than
in C, where it's a full-fledged (but rather special) "type." An
argument that `void' in Java should behave like `void' in C seems
to me to be on shaky ground; one might make a similar argument
about `goto'!
Finally, Java's lack of a C-style preprocessor removes some
of the incentive for hyper-abbreviated logic. In C macros one
sometimes has a need to cram what would ordinarily be a statement
into a context where an expression is required, and both the
`void'-operand ?: and , operators are handy for this purpose, if
more than a little obfuscatory. Take away the preprocessor and
the need for that kind of condensation, and you take away most of
the reasons for not writing if/then/else in the first place.
private final class FlameResistantSuit
extends WhatIWasWearingBefore { ... }