Java Gotchas

Java

  • Everything is a pointer that initially points to null. Every non-POD type must be newed (I forget this one a lot)
  • The POD types (int, float, enum, etc.) behave just like their C++ counter parts.
    The boxed versions (Integer, Float) and String in Java are more like a pointer to the POD value.
    For example:

    String a = "chris";
    String b = "chris";
    if (a == b) System.out.println("The strings are the same");

    This test will always fail because operator== for pointers (Instances of anything derived from java.lang.Object) will test if the pointers point to the same memory.
    To compare boxed types:

    if (a.equals(b)) System.out.println("The strings are the same");
  • Strings are immutable in Java, this doesn’t work as expected:
    String a = "a";
    a.replace('a', 'b');
    System.out.print(a); // Prints "a" instead of "b"

    A copy must be made:

    String a = "a";
    String b = a.replace('a', 'b');
    System.out.print(a); // Prints "b"

    String toUpperCase and toLowerCase have the same problem.

  • Java finalize() is not a C++ destructor.  It is not guaranteed to be called.  If a finalize() function is called it is up to the child class to call super.finalize().
  • If you specify no access modifier in C++ the default behaviour is private to the class, in Java it is private to the package. If you are bitten by this bug it kind of serves you right because you should always specify an access modifier anyway, but it may bite you when porting old code from C++.
  • There is no way to choose what lives on the stack and what lives on the heap. It doesn’t really matter most of the time, but it would be nice to have the option.
  • There is no passing by reference, everything is passes as a pointer.
  • There are no function pointers, anonymous interfaces are probably the closest thing to it.
  • Copy vs Reference Confusion
    Car a = new Car();
    a.SetColour("red");
    Car b = a; // Takes a reference to a, does not create a copy
    b.SetColour("blue");
    System.out.print(a.GetColour()); // Prints "blue"
  • Java final is not the same as C++ const
    class PaintShop {
      public void PaintCarBlue(final Car car) {
        car.SetColour("blue"); // Changes the colour of the original car
      }
    }
     
    PaintShop paintShop = new PaintShop();
    Car a = new Car();
    a.SetColour("red");
    paintShop.PaintCarBlue(a);
    System.out.print(a.GetColour()); // Prints "blue"

Eclipse

Last time I tried Eclipse (10 years ago?!?) it was incredibly slow. JVMs and Eclipse have both improved remarkably in that time, and Eclipse is now just as fast as KDevelop. There are many nice features that I haven’t seen in other IDEs yet such as a warnings and errors panel that compiles your project in the background. The special feature here is that for every warning and error, Eclipse will offer a few possible solutions to solve it, for example “import java.util.io.File is never used” will offer a few solutions, “Remove unused import”, “Organise imports” and “Add @SuppressWarnings ‘unused'”.

Helpful warnings about unused import
Helpful warnings about unused import

Clicking on “Remove unused import” will automatically remove the line from the code.

Possible solutions, selecting one will make it happen.  I'm not sure what is up with the colours on the example being inverted, perhaps so you don't confuse it with your application's code?
Possible solutions, selecting one will make it happen. I'm not sure what is up with the colours on the example being inverted, perhaps so you don't confuse it with your application's code?
  • There is also automatic adding of imports for the classes used in this file, extracting public classes to new files, creating new packages/classes/methods/variables/enums, add cast to make classes convertible, change type of object to match, rename a similarly named class/method/variable/enum to match this reference to it, change this reference to a similarly named class/method/variable/enum, and what seems like many, many more.
  • There is a way to change how many spaces wide a tab is, but there is no way to insert spaces instead of tabs (I’m sure there is a way to do this but I couldn’t find it).
  • The auto completion feature works as well as modern versions of Visual Studio which is something I have been sorely missing in KDevelop.  Good auto completion is quite rare. Admittedly the C++ case is more complex.  Includes, defines and ifdef/ifndef, mean that a state machine and parsing of all previous code is required to get an accurate auto completion list. Early versions of Visual Studio for example got this very wrong.
  • When it is working, warnings and errors as you type is very handy.
  • Debugging is a bit clunkier compared to KDevelop and Visual Studio (But at least it works which is more than I can say for debugging C++ applications in Xcode (Perhaps Objective C debugging actually works but no one at Apple cares about Carbon any more?)).
  • Various for and while loops can be auto completed using arrays, arrays with a temporary variable, collections and iterators.
  • The create new variable/function/class/file wizard not only works but is actually useful.
  • Refactoring is phenomenal, for example “Extract method” will find similar code throughout the whole class to extract, not just the current selection in one function.

Java

I’ve been getting back into Java in my spare time recently, as I think about possibly making a few Android games. These are some notes about the differences between Java and C++.

  • In Java (almost) everything is an object. Strings, Floats and Ints are first class types.
  • In C++ we usually don’t have to stress too much about performance. We can usually afford to do extra processing, create and pass around as many temporaries as we like, use extra ram and hold onto large amounts of ram. Java dies if you use too many temporaries. Performance in Java is highly reliant on the algorithms used.
  • Java benefits from lazy initialisation, not doing anything you don’t need to until you need to.
  • Caching previous results (But not holding onto excessive amounts of ram).
  • Reducing number of temporaries by using classes such as StringBuilder.
  • Java is fun to use. Like a strict C++. Strict in a good way. It is how C++ should have been created. Unfortunately the C++ standards committee decided that backwards compatability was a higher priority than creating awesomeness.
  • The built in libraries are pretty good. I can still write algorithms quicker in C++ but there is a lot more extra functionality in the standard Java libraries such as regular expressions, file system, networking, threads, gui and sql. This is changing slightly with C++0x, but it still lacks basic things such as XML parsing, sql and anything related to gui.
  • Each file can only contain 1 public class. This enforces good structure on your API, “what is the public interface going to be?”, where in C++ a lot of APIs just throw all classes in the header and allow the user to do whatever they want.
  • Using classes from other files is less broken. The lack of including is a good thing although packages and import are basically the same as namespaces and include/using.
  • Being forced to catch exceptions is great, the compiler makes sure that you are doing something with the exceptions later. If you throw or rethrow an exception you then have to mark your function as “throws ” so that the exception and catching the exception propogates up the call stack. The best part about this is that the compiler then knows exactly where an exception should be handled and produces an error if you haven’t handled it or rethrown it.
  • I miss const. There is final but it isn’t quite the same.
  • I miss for example operator overriding. Some built in classes such as String, Array, Vector, etc. could definitely benefit from it. buffer[0] is easier for me to write and understand at first glance than buffer.get(0).  Geometric vector and matrix classes could definitely benefit from operator overloading too for example a = b + c can be understood instantly, a.Add(b, c) is a bit awkward and I have to think about it, “a is being modified, right, b and c are left unmodified, right?”.
  • I miss complex macros and ifdef/ifndef. These can be very helpful, for example using one class on one platform and another class on the other or sharing all the code in a class except for a few lines that are different. Apparently the JVM should be good enough that you can branch on the platform and use oop to change functionality and not lose too much performance. I’m not sure what the replacement is though for a part of your application that just doesn’t compile on other platforms because it uses a platform specific API.