Java Design Flaws

Flaw concerning this page: below it says "describe (in the linked page) why the design flaw is actually a problem. Please keep the list clean by removing entries that have neither votes nor a linked page.". Well, I'd like to add TheLclass (which I did not write, incidentally) to this page, but the rule says that I can't without doing extra work. I should just be able to link TheLclass, and others could later add the votes, add a better description of the problem to TheLclass page, and also I should be able to list a Java problem that does not yet have its own page -- unlinked WikiWords are part of the WikiWay. But I sure as hell am not going to get into an edit war about this.

"Removing entries that have neither votes nor a linked page" means that if an entry has either votes or a linked page, it's fair game. Not a flaw, and add away.


Why ?

This page describes design flaws in Java. In a manner more constructive than a LanguagePissingMatch, we ponder how the language could be made better at reasonable conceptual or implementation cost, and hopefully glean applicable insights along the way.

What goes in this List?

In short, design flaws. Those which affect the language itself, or the Core API classes which no programmer could possibly avoid being aware of - collections, Object, Thread... We don't want a list of bugs in Sun's Java implementation. If it can be easily fixed, it may not go on the list either. If it can't be fixed without making Java a totally different language, it's not really interesting either. What we want here is a list of serious mistakes in Java, so that we can avoid them in the future.

Please keep the list ordered according to the number of votes.

Please choose titles such that a person who does not know what you are talking about gets the idea. Furthermore, describe (in the linked page) why the design flaw is actually a problem. Please keep the list clean by removing entries that have neither votes nor a linked page.

  MessyExceptionHierarchy . . . . . . . . . . . . . . . . votes: 16 (antivote: 0)
  CheckedExceptionsAreOfDubiousValue  . . . . . . . . . . votes: 12 (antivote: 11)
  NoRealJavaMetaModel . . . . . . . . . . . . . . . . . . votes: 14 (antivote: 1)
  CloneableDoesNotImplementClone  . . . . . . . . . . . . votes: 9  (antivote: 4)
  JavaArraysShouldBeFirstClassObjects . . . . . . . . . . votes: 8  (antivote: 1)
  EveryObjectIsaMonitor . . . . . . . . . . . . . . . . . votes: 8  (antivote: 2)
  JavaPrimitiveTypesShouldBeObjects . . . . . . . . . . . votes: 8  (antivote: 3)
  UnmodifiableListIsStupidAndItBreaksLsp  . . . . . . . . votes: 5  (antivote: 2)
  JavaExceptionsShouldBeInterfaces  . . . . . . . . . . . votes: 4  (antivote: 4)
  JavaObjectOverheadIsRidiculous. . . . . . . . . . . . . votes: 4  (antivote: 3)
  JavaArraysBreakTypeSafety . . . . . . . . . . . . . . . votes: 3  (antivote: 4) (not fixed in JDK 1.5 - generics ea 2.0 only)
  JavaIoClassesAreImpossibleToUnderstand. . . . . . . . . votes: 3  (antivote: 5)
  JavaExecIsaTotalMess  . . . . . . . . . . . . . . . . . votes: 4  (antivote: 1)
  JavaStaticClassesIsaTotalMess . . . . . . . . . . . . . votes: 3  (antivote: 2)
  NoMultipleDispatchInJava. . . . . . . . . . . . . . . . votes: 4  (antivote: 3)
  DeprecatedInterfaceMethodsCreateUnavoidableWarnings . . votes: 2  (antivote: 4)
  FinalizeInsteadOfProperDestructor . . . . . . . . . . . votes: 3  (antivote: 9)
  JavaOldSyntax . . . . . . . . . . . . . . . . . . . . . votes: 2  (antivote: 1)
  JavaDocumentModelBreaksEncapsulation  . . . . . . . . . votes: 2  (antivote: 0)
  StaticMethodsNonPolymorphic . . . . . . . . . . . . . . votes: 2  (antivote: 1)
  JavaFloatingPoint . . . . . . . . . . . . . . . . . . . votes: 1  (antivote: 0)
  JavaLacksLanguageSupportForLists  . . . . . . . . . . . votes: 0  (antivote: 0)
  JavaInterfacesCannotSpecifyConstructors . . . . . . . . votes: 1  (antivote: 3)
  JavaAutoboxingIsNot . . . . . . . . . . . . . . . . . . votes: 1  (antivote: 0)
  JavaDateClassIsNotImmutable? . . . . . . . . . . . . . . votes: 1  (antivote: 0)

(Note to everyone else who edits this file: the list above needs to remain monospaced.)
Items previously above that were accurate critiques, but were fixed in the Java Language, and therefore removed from the above list:

  NoCovariantReturnTypes  . . . . . . . . . . . . . . . . votes: 15 (antivote: 0) (fixed in JDK 1.5)
  JavaLostEnumeratedTypes . . . . . . . . . . . . . . . . votes: 7  (antivote: 3) (fixed in JDK 1.5)
  ChoiceOperatorDoesNotConsiderInheritance  . . . . . . . votes: 5  (antivote: 2) (fixed in JDK 1.5)
  IteratorSemanticsAreWrong . . . . . . . . . . . . . . . votes: 3  (antivote: 2) (fixed in JDK 1.5)

Items previously above that were not accurate critiques, and therefore were removed from the above list:

  JavaEmptyListIsBroken . . . . . . . . . . . . . . . . . votes: 3  (antivote: 1) (it seems this is simply false)
  SetsBreakCollectionContract . . . . . . . . . . . . . . votes: 2  (antivote: 6) (while the claim has some merit, it probably shouldn't be on this list)

A link to this page was posted on comp.lang.java.advocacy by ThomasHolenstein?. Given the number of anti-Java bigots that hang out there, I don't expect any reasoned debate or unbiased voting to ensue.


Is it me, or do a lot of these complaints boil down to either "Java Isn't Smalltalk" or "Java Isn't C"? The "Choice Operator" (?:) one, especially, is something that has never bothered me, and that I probably would never have even encountered. But I can see how it would loom large for someone who fell in love with ?: while coding lots of C.

Would that all software had such severe flaws. --GeorgePaci

I think that the items with the most votes (and the choice operator item) highlight conceptual inconsistencies within the language, rather than wishes that Java was more like another language. Issues such as arrays breaking type safety, operators not working with Java's inheritance model, lack of covariant return types, or reservations about exception handling come from a desire for Java to have as few "warts" as possible. -- AnonymousDonor

Yes, many of these complaints are indeed saying "Java Isn't Smalltalk/C/C++/Lisp." However, it's important to note that Java was designed to be an 'ideal' combination of these languages. The complaints above, under this light, are indeed flaws; they are areas where the designers of the JavaLanguage placed a very different priority on a certain feature than the developers who ended up using the language would have. No, many of them are not flaws in the sense of contradictions or defects; however, they are flaws in that the language did not live up fully to its design goals. Of course, on another note, I'd say that Java has done a better job of living up to its goals than any other language, with the possible exception of SchemeLanguage. -- AdamBerger

That ("better job of living up to its goals than any other language") seems like a strong statement, unless you mean it in PaulGraham's take on Java ("intended to be a language for the masses" / "and therefore not desirable for smart people"), which I doubt you meant. :-) But obviously you have some specifics in mind; share? -- DougMerritt

My company (ComponentSoftwareCorporation?) and I participated in the creation of Java, we were there when it was born, and I can tell you that the original design goal was to provide Smalltalk functionality with C-like syntax. Two dimensions of that goal are relevant to this page: Java-the-environment and Java-the-language. Regarding Java-the-language, the first choice was CeePlusPlus. When we demonstrated that CeePlusPlus semantics precluded making Java-the-environment be sufficiently like Smalltalk, the next choice was ObjectiveCee, which we extended with a type system and for which we built and delivered to Sun a VirtualMachine. That VirtualMachine became the early JavaVirtualMachine. Java-the-language was syntactic sugar that was semantically equivalent to our extended ObjectiveCee. All of this is to say that the complaint that "Java isn't Smalltalk" is, in fact, a historically accurate starting point for identifying its design flaws. It is perfectly reasonable, in that context, to also discuss SmalltalkDesignFlaws?. -- TomStambaugh


JavaNewIo ??


I wonder if we would better use a WikiWeightedVote or a WikiMultipleVote. Now, recent entries don't have a chance to get to the front of the list. What do you think?
How about:

New items to vote on:

  JavaExceptionSystemLacksFunctionality . . . . . . . . . votes: 1


Does weak expressiveness count? A line or two of Haskell, Ocaml, Lisp, or Scheme can often do the work of ten lines of Java (which is up there with other painful languages, like C/C++). (JavaLacksRealMacros?, JavaLacksDataDescription?, JavaLacksSymmetry?)

Java is "protection-oriented" language in that it uses verbosity to help the compiler verify things fit the programmer's or library builder's intent. Generally there is a trade-off between verbosity and protection. However, there are some annoying features that seem like they could have been done shorter without losing protection. Examples:
  bigClassName foo = new bigClassName(x);
This seems redundant and is a common pattern. Although it's possible the "type" can be different than the class, if it's not, then it should somehow default to being the same:
  foo = new bigClassName(x);  // suggestion 1: type assumed to be "bigClassName" if omitted.
  * foo = new bigClassName(x);  // suggestion 2: wildcard char to indicate "bigClassName" 
  bigClassName foo = new(x);  // suggestion 3: "new" constructor shortcut. Full version still allowed if wanted. 
  bigClassName(x) foo;  // suggestion 4: combo type-and-constructor
And:
  System.out.println(x);  // Surely they could have built a short-cut
[Indeed. For this, you want C#'s 'var' keyword or Scala's 'val'. It's somewhat surprising that it wasn't introduced in Java 8, but it wasn't. As for System.out.println(), it's almost never used in production code unless you create command-line utilities, and then it's trivial to create your own short-cut like PrintStream p = System.out; p.println("zot"); p.print("foop"); ... etc.]

You are right about production systems, but it bloats up examples and debugging code.

[You can fix it, like I did. See above re PrintStream p = System.out;]

But one has to repeat it for each class, and it varies per author. A commonly-recognized and global shortcut would be the ideal.

{I'm not a Java expert, but is there some reason you can't do?}

  import java.lang.System.out;

out.println(x);
[It can't be done because System is a class and 'out' is a public member of System. You can import classes and packages of classes, but not members of classes, and all class members must be explicitly qualified by a class name (if and only if the member is static) or a reference to a class instance.]


CategoryJava CategoryIndex

EditText of this page (last edited April 24, 2014) or FindPage with title or text search