You used an outdated computer 3 years ago. Not really Javas fault.
I think most agree that multiple inheritance and explicit deallocation
of memory is a bad thing.
C++ templates can do some things that Java generics can not. And
vice versa. They are simply relative different concepts.
You can do things with multiple inheritance that can never be done
with interface implementations alone. Can it be abused? probably.
Does that justify tieing the programmers hands? I would argue no.
I find the statement that "explicit deallocation of memory is a bad
thing" to be laughable. It assumes that this MUST be done in C++. If
you look at boost shared pointers and the like you will find that
object lifetime can be easily and, more importantly, predictably
managed. There seems to be an implicit assumption in this rather
childish statement in the philosophy behind garbage collection that
memory is the only resource that must be managed. File handles,
network connections, and other resources that are just as important to
manage and must be managed in a way that is more deterministic that
can be done by relying on garbage collection. The result is that, if
you code a class in Java that must manage one of these resources, you
MUST add methods that allow the application to release the resources
and these MUST be invoked before the object reference is released.
So, tell me again, how does GC really help here??
There are a lot of other "features" of Java that I find very
annoying. Examples:
- Lack of unsigned integer types. I realise that, with two's
complement math, the math operations between signed and unsigned is
all the same. However, I find that not being able to use unsigned
types results in sign extension in places where it was not expected
and results in casting/masking operations that only serve to clutter
the source code.
- Bit shift operations only appear to be implemented for the integer
type. The result: if I am trying to do bit shifts on something
smaller than an integer, a byte or a short, the arguments are promoted
to integers and the reslt of the shift is an integer. So in order to
assign that back to something smaller than an integer, guess what,
yet another cast is needed.
Me measure of the "goodness" of a language or its implementation is
whether I can accomplish the task I set out to do without having to
fight the language or its implementation. If I have to litter my code
with cluttering casts simply to produce the correct results or to
satisfy the childish demands of the compiler, I become annoyed. If
the language hobbles me rather than allowing me to express the design,
it also becomes annoying. My personal experience is that Java is
cluttered with these kind of issues.
It seems to be easy to forget that there are reasons for writing
programs that transcend the language or environment in which it is
developed. At the end of the day, my value to my employer is not in
the languages I have mastered but in what I can produce that can solve
our customers problems and/or needs. To the extent that the language
and/or environment facilitates that, it becomes a valuable tool. To
the extent that the language/environment fetters that, it becomes less
valuable and less likely to be chosen as a tool. No language or
environment is free from blemish. Java has some real advantages but I
do not consider it a replacement for what can be done in C++.