Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Java has been one of the most (the most?) popular programming languages till this day, but this also brought controversy as well.

A lot of people now like to bash Java simply because "it's slow", or simply because it's not language X, for example.

My question isn't related to any of these arguments at all, I simply want to know what you consider a design flaw, or a poor design choice in Java, and how it might be improved from your point of view.

Something like this.

share|improve this question

closed as primarily opinion-based by MichaelT, Bart van Ingen Schenau, GlenH7, Kilian Foth, Dan Pichelman Jul 5 '13 at 5:27

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.If this question can be reworded to fit the rules in the help center, please edit the question.

34  
Java is not slow –  Anto Feb 22 '11 at 17:36
3  
being slow was actually a design choice - they got it right first. –  user1249 Feb 22 '11 at 17:45
28  
"Java is not slow" - said with 9 min delay. –  user8685 Feb 22 '11 at 17:46
3  
@Frustrated and yet that has nothing to do with language, it has to do with implementation. –  Woot4Moo Feb 22 '11 at 18:19
5  
I just heard a talk on the java Tomcat web server. They did numerous benchmarks against the C Apache web server - which is widely considered faster. Except it isn't. Tomcat was faster in every benchmark. –  Chuck Stephanski Mar 18 '11 at 18:34
show 18 more comments

18 Answers 18

up vote 27 down vote accepted

Small programs require quite a lot of code. I dislike how it is so tightly locked to the object oriented model.

share|improve this answer
1  
As a Java programmer, I think the two you just mentioned are the most annoyances I have with the language, therefore, I'm choosing this as the answer, thank you –  Mahmoud Hossam Feb 23 '11 at 21:53
show 1 more comment

Checked exceptions, and exceptions for error handling

A pox on an otherwise nice language is its exception handling model.

Java badly abuses this. Too many times, there are simple operations (like generating a SHA-1 hash) that cannot possibly fail, and yet throws multiple checked exceptions. In methods that have a very simple failure condition (which is handled in other languages by returning null or an empty value), Java implementations instead throw very confusingly-named exceptions.

Someone pointed out to me that "if you're hashing an object, that object needs to be serialized first, right? If it can't be serialized, it can't be hashed." This is ridiculous. The compiler should be capable of detecting that the object does not implement a serializable interface and immediately return a static type error. Function that accepts a string (and that has well-defined semantics for all input values) should never be able to accept an object that cannot be converted to a string, never mind throw an exception in that case.

Generics

A sad attempt to mimic C++ templates that fails utterly. C++ templates and Lisp-style macros are far and away more powerful than anything Java has to offer. Java took the obvious part of C++ templates (generic typing) and threw out all of the useful parts (like code generation).

This has led to extensive and wasteful code duplication and type erasure, both of which would be considered serious problems in any other statically-typed language.

Yes, I know C++ templates are difficult to use and debug. But they are also extremely powerful, granting the power of compile-time computation and code generation with what is a complete declarative pre-processing language. It allows one to create a vector of anything and still have the power of static type checking everywhere it's used. But in Java, you get an ArrayList that may or may not hold what you're trying to put in it. (Oops, there's another exception minefield! Why doesn't it statically check? Oh, right, it erased the type information.)

"Beans"

If I have to write one more useless getter/setter pair, I'm going to kill someone.

The whole concept of "Java Beans" violates principles of good OO designleft and right:

  • Having public getters/setters (which rarely do anything beyond assignment or return) for private members violates encapsulation. With trivial getters and setters, the field may as well be public. What, then, is the point of having getters and setters? A class should manage its internal state like a black box.
  • It violates YAGNI -- if you ain't gonna need it, why write it? Frameworks that use Beans should be smart enough to use a public member as a public member and treat private members as if they don't exist. If you really need a setter or a getter, it should be smart enough to use it when it's there, and access the member directly when it's not. It only makes sense.

I have other complaints about the core language, but I've not used Java extensively enough to explain why I believe them to be flaws.

share|improve this answer
7  
@Phobia: It's the abuse of exceptions for every little error condition that I object to. When a simple string processing method has to throw an EncodingError exception instead of something sensible, there's a problem. In C++, we use exceptions sparingly: new throws bad_alloc when memory is exhausted; but sort doesn't throw an exception if the list is of length 0. –  greyfade Feb 22 '11 at 17:55
21  
+1 for "useless getter/setter pair" –  ldog Feb 22 '11 at 18:16
11  
C++ templates are difficult to debug, unlike Java's generics –  Mahmoud Hossam Feb 22 '11 at 18:31
4  
@greyfade: C++ exceptions are hosed. Generics in Java do what templates in C++ should be used for, and do so unambiguously. I've never seen a Java generic compiler error anywhere near as epic as some things I've seen from Boost, or even the STL. –  user18014 Feb 22 '11 at 20:48
8  
@Phobia: Writing templates is tricky. Using them is a lot less tricky, particularly once you get a compiler with reasonable template error messages or learn how to read the unreasonable ones (and that's a skill that really doesn't take long to acquire). –  David Thornley Feb 22 '11 at 21:50
show 19 more comments

Security model It's so bad most people don't ever want to use it. Seriously, if you want to provide finer-grained security than per JAR file you have to go through some serious hackery. I know, because I've done it. Who has ever taken the time to set up a sandbox and configure the permissions for it? Most people just use the fail safe AllPermissions and call it a day.

Class Loading Ever try to load a generated class at run time? How many errors have been attributed to the way class loaders resolve classes? Class loaders are made even more obtuse because it is tied with the broken security model. Loading a plugin that relies on a specific version of a library? It can fail if you already have a different version of the library in a parent class loader. Yes, I've done a lot of server and framework work.

RMI Remote Method Invocation, good idea in theory. Too bad every single method in your interface must throw the checked RemoteException. Let's not even talk about how it will silently attempt HTTP tunneling if your SSL connection fails.

Checked Exceptions that will never be thrown: Ever needed a MessageDigest for SHA-1 or MD-5? These are standard implementations that are a part of the core install. Unless someone is screwing around with your install, the call to MessageDigest.getInstance("SHA-1") will never fail. Same with a number of File API calls.

Generics: Not only do the Generics system not respect the normal object type hierarchy, it only provides superficial support. Just enough to ruin your day, but not enough to help. The wild card system are also a smell that the generic typing system isn't right. Just check this out if you have doubts. And how many times have I wanted to perform a new T() like you can with C++ or C#.

share|improve this answer
1  
+1 for Security model. Ugh. –  Greg Feb 22 '11 at 23:39
1  
or T.class. no such luck. –  Chuck Stephanski Mar 18 '11 at 9:51
show 1 more comment

Primitive types. Everything should be treated as an object. (Note that integers, floats, etc. can still be represented internally using native types, but they should be exposed as classes, not "something else".)

share|improve this answer
1  
You can wrap primitives in objects in Java. Don't know how Ruby or Python do it, but I would assume they do the opposite. Everything is an object but gets converted to a primitive before it's manipulated. I know javascript converts between the two at it's own discretion...which is actually pretty nice. But slow. –  Anthony Shull Feb 23 '11 at 0:10
1  
In Python, everything has reference semantics. –  dan04 Feb 23 '11 at 1:39
show 3 more comments

A noun-oriented design: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html

share|improve this answer
3  
Any OO languages is data-centric, true. But Steve Yegge's noun-oriented Java story suggests that Java goes too far. Most OO languages let you have functions that aren't object methods. –  nmichaels Feb 22 '11 at 22:33
1  
@ChuckStephanski actually, since you can't override static methods, that approach can lead to tightly coupled code that can't be unit-tested. –  Eric Wilson Aug 23 '11 at 1:00
show 3 more comments

My main meta-gripe with Java is excessive focus on simplicity of the language specification and making life easy for language lawyers. It only allows you to program in one paradigm (OO) and only at the middle levels of abstraction (OO, garbage collection, nominative typing). Both very high level programming (metaprogramming, code generation, macros, closures, generic/duck/structually typed code) and very low level programming (pointers, manual memory management, inline assembly language, type punning, super performance-critical code) can't be done well in Java.

share|improve this answer
show 1 more comment

The switch statement, which was lifted bodily from C. Stroustrup's design goal included as much C compatibility as possible, so he had no choice. Java could have changed it to something that didn't have default fallthrough, and ideally to something that could take non-integral case values.

share|improve this answer
4  
As of Java 7, it'll accept strings and other non-integral values blogs.sun.com/darcy/entry/project_coin_string_switch_anatomy –  Mahmoud Hossam Feb 22 '11 at 17:41
1  
I'm not holding my breath for it, as it'll take ages to get adopted by the enterprise, as those are the main users of Java these days –  Mahmoud Hossam Feb 22 '11 at 17:45
1  
As for C++ the Java designer wanted it to be as easy for C programmers to come over to the dark side as possible. That required supporting switch too. –  user1249 Feb 22 '11 at 17:47
3  
Hmmm, I'd put the switch statement (and default fallthrough) down as one of the positives, not a negative. Looking forward to the non-integral values though! –  Brian Knoblauch Feb 22 '11 at 21:22
2  
One of my CS professors said of the C switch statement, "It was made from pieces of the language that were lying around." –  Chuck Stephanski Mar 18 '11 at 9:48
show 4 more comments

I don't like how it forces so many of its developers' ideas about what are good coding policies on you.

Besides that though, the API is actually pretty well designed and if you're going to be stuck in the OO model its actually a decent language.

That bit of annoyance though is a big one. It's basically why I absolutely hate the language.

share|improve this answer
1  
They tried to make it hard to abuse the language and make it easy to learn at the same time, the API is very good, but I admit it's a little overwhelming, but that's not a design choice, that's more related to the Java platform, not the language –  Mahmoud Hossam Feb 22 '11 at 17:48
1  
It does help for consistency, though I don't think that redeems it. –  Michael K Feb 22 '11 at 17:52
2  
@Phobia: Correct - you don't have to know the whole API to program. I've implemented parts of it before that I simply didn't know were there! But I've since learned how to search the docs better. The generated documentation really is good, and is one of the reasons Java has been successful. –  Michael K Feb 22 '11 at 17:54
1  
Yeah, the integration of Javadoc within IDEs sure has helped people to learn the language on the go –  Mahmoud Hossam Feb 22 '11 at 18:01
3  
@jsternberg Not being able to reverse a string is hardly an API failure. I mean, How often do you need to reverse a string? –  toc777 Mar 31 '11 at 17:50
show 2 more comments

I/O

  • If you're going to make a language that doesn't have deterministic destruction, it would be really helpful to minimize the number of objects that have to be close()d.
  • Asymmetry between System.out being a PrintStream and System.in being an InputStream.
  • IOException is a major source of the checked exception annoyances.
share|improve this answer
add comment
  • Functions are not objects
  • Being (crazily) religious about OOP.
  • Verbosity (includes lack of operator overloading)
  • Checked exceptions
  • Static typing
  • Lack of some OOP concepts like multiple inheritance/mixins.

I think my main problem with Java is that it presumes the programmer is going to make mistakes and proactively tries to prevent them at compile time. This may be a good thing for some - especially newbies, but it just ends up getting in the way of someone who knows what he's doing.

share|improve this answer
1  
if you want nothing that "can get in the way" you should code exclusively in assembler (or maybe go back to poking bits and bytes directly). Any more advanced language will impose some sort of structures on you. –  jwenting Mar 18 '11 at 11:03
show 8 more comments

My biggest issue with Java is JAR files. The most brain dead thing in the whole world of Java is that once you've written your applications it's a pain the ass to deploy it properly. One of the simplest mistakes is that it's unnecessarily difficult to consolidate an app and it's dependencies into a single JAR. On top of that, you can't modify the classpath when you invoke the JVM so you have to dictate at packaging-time where the log4j.properties is allowed to be located.

Oh, and classpath resolution is also a pain in the ass. Have you ever wanted to use the latest version of Apache's Xalan-J in your project? For one of my customers, that alone meant a 2 week delay because it had to go up to the OS guys for approval and installation.

Packaging and classpath resolution are really my only two gripes with Java. I agree that it takes a bit too much ceremony to make small apps, but that's true of almost every statically-typed, compiled language. And that's why we have Perl/Python/Ruby/Groovy.

share|improve this answer
show 1 more comment

Any variable in Java contains either a value of some type, or null. So if you have String s; you can't guarantee that s refers to a String. All you can say is that it's either a String or null. Yes, sometimes nulls are useful, but more often, you want something that you know is a String. The way this is solved in Haskell, among many other languages that seem to be getting a lot of attention lately, is that if you want a String, you say String, and if you want "something that is either a String or null" then you use a Maybe String which is either Just "someString" or Nothing. No NullPointerExceptions and no if (x == null) { ... } code.

share|improve this answer
2  
+1 Java forces you to write a huge amount of unnecessary type information everywhere but it isn't statically type safe. –  Peter Graham Aug 23 '11 at 2:26
show 1 more comment

I think this page covers it pretty well. There's also a pretty good list here.

share|improve this answer
show 2 more comments

Array typing is covariant, which is simply wrong. This isn't a poor design choice as much as an outright bug.

E.g. a String[] is an Object[].

Object[] objectArray = new Object[1];
objectArray[0] = new Integer(0);
String[] stringArray = objectArray;
String s = stringArray[0]; // type error

The correct way to do this is to make array typing contravariant, i.e. if an A is a B then a B[] is an A[]. A simpler way to get this right is to not make arrays polymorphic in the first place.

Worse still the C# designers copied this bug from Java in 2000.

share|improve this answer
add comment

There are a lot of things to hate about Java, but only so many actual mistakes that were made.

Whether Java is dead or dying is debatable, but it's certainly dead to me. Between Java's language-mandated verbosity, culture-mandated ceremony (such as "useless getter/setter pairs") and disdain for powerful tools such as first class functions (still no closures!), I'd rather stab myself in the eye with a fork than get a job as a Java-developer.

However, if I were in the 90s, trying to sell a segfault-free language to enterprises and C++-developers who believe that garbage collection is not suitable for real work, I might create a language that would look a lot like Java.

I would make it like C++ if I can, including "deliberate acts of fraud" (quote by Gosling) to make C++ programmers think that this is something they are familiar with.

I would make the language and culture restrictive, because the masses of mediocre enterprise-programmers need to be kept in check.

I don't like Java, but without it, we might still all be programming in C/C++, because dynamic languages with garbage collectors would still be considered toys and there would be nothing in between.

share|improve this answer
8  
Java is far from dying/dead –  Mahmoud Hossam Feb 22 '11 at 22:14
1  
closures will be here in 2012. you can even test drive it. mail.openjdk.java.net/pipermail/lambda-dev –  Chuck Stephanski Mar 18 '11 at 4:24
1  
yeah from what i've heard the two most requested features are mixins and reified generics. we are going to get something vaguely like mixins as part of project lamda. the syntax and methodology in the current proposal as designed by java's chief architect brian goetz is breathtakingly awful. hopefully it will get revised before its release in JSE8. –  Chuck Stephanski Mar 18 '11 at 10:01
show 2 more comments

No multiple inheritance. And NO MI is not "bad" or "not object-oriented" or any other such rubbish. It's an incredibly powerful tool which would have required the language designers to look beyond the complete catastrophe that is C++ MI and develop a sensible syntax, which is certainly well within the range of the possible.

As Bertrand Meyer has stated, one of the reason most often given for lack of inclusion of MI in OO programming languages is that it's "difficult to implement". Well then, I guess you shouldn't be building compilers. I'm sure there are other features of modern programming languages that are difficult to implement as well.

I am desperately sick of writing delegation layers and passing the this pointer to the side class and pretending that object identity is retained, and of course you have no polymorphism/overloading.

share|improve this answer
4  
I've been using Java since 1997, and C++ before that, and NEVER needed MI. the few cases I've experimented with it the problem would have been better solved without it. Same for everyone else I know. –  jwenting Mar 18 '11 at 9:51
2  
If you are designing a system with a large object model, especially one with lots of behavior that can be factored across objects it's absolutely invaluable. –  Chuck Stephanski Mar 18 '11 at 18:45
show 2 more comments

The designers carried forth the "dangling else" problem from C. Modula is based on Pascal which is based on Algol. However, Wirth eliminated the "dangling else" problem when he designed the grammar for Modula. For those who are staring at the monitor, the "dangling else" problem is a grammatical ambiguity that is introduced by the grammatical productions "if-statement" and "if-else-statement." The dangling else problem is the reason why we have to write code such as:

if (expression)
  { 
     if (some_other_expression)
        some_statement;
  }
else
  some_statement;

Contrary to popular belief, the curly braces in Java, C++, and C are not part of the of the control structures. Curly braces belong to a grammatical production known as "compound-statement" (a.k.a. "block"). The grammatical productions for "if-statement" and "if-else-statement" are:

if-statement ::= "if" "(" expression ")" statement

if-else-statement ::= "if" "(" expression ")" statement "else" statement

statement ::= if-statement | if-else-statement | for-statement | compound-statement | assignment-statement ...

coupound-statement ::= "{" statement-list "}"

statement-list ::= statement | statement-list statement

Now, let's examine the "dangling else" problem in action.

if (expression1)
   if (some_other_expression)
      some_statement;
else 
   some_statement;

To which "if" does the "else" belong? Using the above grammatical productions, the code can be parsed as an outer "if-else-statement" with an inner "if-statement" or an outer "if-statement" with an inner "if-else-statement" Since "if-statement" and "if-else-statement" are both statements, the parser has no way to determine which “if” should be matched with the “else.” The practice of matching the innermost “if” with the “else” is a deus ex machina technique that is forced into the grammar by the compiler writer.

Let’s examine the first example in detail.

if (expression)
  { 
     if (some_other_expression)
        some_statement;
  }
else
  some_statement;

The above code snippet works as expected because it gets parsed as an outer “if-else-statement” with an inner “compound-statement.” The production for "compound-statement" is resolved before the parser encounters the "else" token; therefore, the innermost "if" that is seen by the parser is the outer "if."

share|improve this answer
2  
So you want an endif? –  user1249 Feb 22 '11 at 20:44
12  
No language can stop programmers from writing bad code. –  zzzzBov Feb 22 '11 at 20:47
1  
I've done time in Pascal, Object Pascal, and Modula-2 land. I miss certain things about them. Their particular if/then/else structure is not one of them. I prefer the Java method... –  Brian Knoblauch Feb 22 '11 at 21:24
1  
This isn't a bad coding issue. It is a language design issue that requires defensive coding to avoid. The "dangling else" problem is a well-known problem in computer science (en.wikipedia.org/wiki/Dangling_else). The issue could have been resolved cleanly by removing the "compound-statement" grammatical production and incorporating the curly braces into the conditional and interative control structures. The language production for "try-catch" already incorporates this grammar modification. –  bit-twiddler Feb 22 '11 at 22:11
1  
@bit-twiddler: its discussion page says it all: there is nothing ambiguous about the construct or its interpretation, it's just that some of the primitive parsing algorithms that are still very much in vogue today can't handle it. But humans aren't better at parsing than computers so we shouldn't be surprised that they have problems with it as well. –  reinierpost Apr 1 '11 at 14:45
show 7 more comments

Main design flaw in Java was making it free, and inventing the JCP to determine what the future of Java is. Mind neither of these are problems with the language, they're problems with the management of the development of the product itself!

Because it's free there's hordes of horrible programmers (and I use the term loosely) out there using it, giving it (in some quarters) a bad name (and giving the entire business a bad name). Because of the JCP, Java is turning into a loose gathering of "language X has it, therefore Java must have it too" as everything under the moon is added to the core language and libraries for no other reason than that it's someone's pet project.

share|improve this answer
5  
VB.NET (or VB in general) isn't free, and it's notorious for having the most amount of horrible programmers. –  Mahmoud Hossam Mar 18 '11 at 8:14
4  
see, it has nothing to do with being free or not, it has to do with the language itself and the learning curve for it, for example, it's really hard to see a "Bad" perl programmer, because the language itself is somewhat harder than other languages. –  Mahmoud Hossam Mar 18 '11 at 14:40
show 1 more comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.