This is a historical discussion motivated by what people complained about JavaDesignFlaws. Some flaws were not exactly design flaws but more likely a trade-off because the first 5 versions (up to and including JDK 1.4) had a simple TypeSystem (no parametric polymorphism).
We may never know who took the decision to keep the type system simple and avoid venturing into more advanced type systems. They may have considered it too risky in the project or simply did not have enough money and people before Java gained a lot of weight, it is certain though that the experiments that lead to the typing system of Java 1.5 took a few years to crystalize.
But, anyway, taking the simple type system as a given, some of the alleged "Java Design Flaws" appear not as flaws but as trade-offs. They are obviously worse than what can be designed in a language with an advanced type system (ML, Haskell) , but on the other hand if you have to live with the limitations some decision were sound engineering decisions.
This happen in many projects: you know that a design decision is not the best there is, but it may be the best that you can accomplish within that context (time / money / people).
Yes, it is (or it was, and was fixed only with Java 1.5).
This is good for minimizing the engineering effort put into the compiler and the JavaVirtualMachine, good for the programmers that ran away from C++ because they couldn't understand lots of things while in Java everything's kind of simple.
This is relatively bad for my esthetic satisfaction when I program in java - I usually get frustrated and I hit the keyboard harder when I have to use the cast operator, but it's definitely bad for the Java static type safety, definitely bad for the HotSpot compiler or any other kind of optimizer which according to my private testing is able to optimize almost nothing at all because of type losses and cast operators. But generally we can work around these issues, until we'll find a better nicer language in which to program and more importantly, get paid.
A lot of people are complaining about what they think of as JavaDesignFlaws, when in fact they should not be considered as such. I have reason to suspect that JamesGosling and comp, knew then and they certainly do now about :
I have no doubt that in the next 10 years we'll have some other language that will deal with these things better, but right now it's factually incorrect to call the above design flaws. The design decision was that they couldn't have made it with a more complex type system (deadlines, lack of money, lack of people, not enough theory to support them at the time or whatever else), so they supplemented the KissPrinciple typing with runtime checks and the all too present cast operator. --CostinCozianu
Good OO type systems were around before Java was defined. Look at EiffelLanguage (which has a flaw, in that it allows CovariantParameters? instead of ContravariantParameters?), SatherLanguage (which fixes the flaw in Eiffel's type system by supporting contravariant parameters) and ModulaThree.
It depends on what you understand by good. I don't think Java's type system is all too bad either, the problem with type systems for OO languages is that they are inherently very complex (at least according to PrinciplesOfObjectOrientedSoftwareDevelopment, "A TheoryOfObjects", and many others). In all fairness, the languages described above have some desirable features that are not present in Java, but they don't have state of the art type systems (I don't know much about Sather, so it might be an exception), and they don't have to suffer some of the constraints that Java has. Maybe we should try to create a history of OO concepts and ideas and how they evolved in different languages, technologies and approaches.
Let me detail:
To introduce CovariantReturnTypes, we have to modify the definition of a method signature and the JVM operations that invokes such a method.
To have arrays as first order object, and to have arrays provide absolute static type safety we can choose either to:
have X[] <:(subtype of) Y[] <=> X=Y or to introduce parametric types in JavaThe choice operator example shown on that page means that the compiler should decide the type of an expression based on the expected type derived from the context. Not an easy thing to do.
No MultipleDispatchInJava?. Any OO language that defines method invocation as x.method(...), instead of just function(...) already gave up on multiple dispatch.
NoRealJavaMetaModel. Well for this metamodel to be real we have to have the a real model. Instead we look like we are happy enough with a simple one.
So yes, I agree that all those things would be nice to have, but they are not design flaws, and we still haven't found a perfect language. Just not yet.
I think that the root cause of Java's growing pains is that it's type system was simplisitic rather than simple.
Exactly. SmalltalkLanguage and especially SelfLanguage have simple type systems: easy to hold in your head, and leading to simpler code.