Java: Good and Bad

by Dejan Jelovic

I've been using Java on a daily basis for about two years now. Some things I like very much. Some things irk me and make my life really hard. This article contains a list of things that have either made my life considerably easier as opposed to the time when I program in C++, or considerably harder.

Good Things

Things that make programming in Java a joy as compared to C++:

1. Inner classes and anonymous classes are cool. C++ doesn't have them, and that sucks big time. (Actually, I'd prefer anonymous functions, as most of the things I write in-place are implementations of one-function interfaces like Runnable.)

2. Reflection (an enhanced version of RTTI) is cool. Good run-time type information makes exposing parts of a program to a scripting engine easy. It also makes things like dynamic proxies and RMI easy to implement without requiring one to use IDL.

3. A controlled environment such as a VM means that there is no chance of corrupting the memory. Thus when a bug happens one usually has much more evidence about what caused it than in a typical native program.

4. Java standardizes on a naming convention that is clean and readable. My eyes hurt when I look at an average C++ program.

5. Java comes with a large standard library. The library has packages for a platform-independent GUI, threads, sockets, encryption, etc.

Bad Things

Here are the things that make me curse Java designers on a daily basis:

1. No support for types with value semantics. I frequently use iterators in my designs. And when I send an iterator into a function, I want to send a copy, not the iterator that I still own and want to use.

2. No resource management facilities. Garbage collector takes care of unused memory, but what about files, sockets, bandwidth and similar resources which need to be disposed of as soon as they are not used any more? In C++ I can do that painlessly by using reference counting smart pointers and destructors.

3. Checked exceptions. Checked exceptions are evil because they put implementation details (which exceptions are thrown) into interfaces. So instead of letting me propagate the exceptions until the place where the transaction started, Java is forcing me to handle them locally because large portions of the standard library use checked exceptions. I get around this by catching them, wrapping them into an exception derived from RuntimeException and re-throwing, but that is both painful and leads to information about the exception being lost.

4. No const keyword. The const keyword is great. It ensures that an object sent into a function will not get changed, which is one of those nice guarantees that a function can make.

5. No multiple inheritance. I've heard all kinds of arguments against multiple inheritance. It's complicated. One can form the "diamond of death" using multiple inheritance. It can lead to bad designs. Yet I have never seen any piece of code that misuses multiple inheritance. Most people simply don't use it. Those that do usually put it to good use and create crisp, elegant designs that avoid tall, monolithic hierarchies.

6. Sun's complacency about bugs. I've hit against numerous important bugs in the Java libraries. After I isolate a bug I usually check the bug database at to see if there are any workarounds. More often than not, I can see that the bug has been reported a couple of years ago, and that Sun has ignored it. To add to the insult, asshole engineers at Sun sometimes close the bug as unreproducible with a comment like "if someone doesn't send me a piece of code demonstrating this bug, I'm closing it." Like they are doing me a favor for letting me report a bug. Jesus.

In all the years that I have programmed under Windows I didn't find as many bugs as I stepped on for the last two years working in Java. And, none of the bugs in the Windows API were showstoppers. Unfortunately, some of the bugs in the JDK are. For example, the clipping region of a Graphics obtained from a lightweight component by calling getGraphics() is wrong. Finding a way around that kind of bug is a nightmare.

7. The Java GUI library does not define an order in which events will be fired, and it does not define exactly which events will be fired when. This means that JDK, IE and Netscape will fire events differently on a single platform, Windows. Throw in additional platforms, and you've got a whole big mess.

8. Java makes me pay, in run-time size and speed, for using data types. If I have a C++ program that counts apples and oranges, I can have types AppleCount and OrangeCount that make sure that I never mix the two. Since these types would are simple wrappers around int and use only inline functions, the end program will be as fast and as small as if I had used int, only more type-safe. Unfortunately, in Java, I have to pay in both program size (as additional .CLASS files are shipped), and in execution speed (the compiler is unable to erase type information from data types used in interfaces).




Content of this site is Dejan Jelovic. All rights reserved.

Photo courtesy Philip Greenspun.