: code tutorial (v3)

Lesson 5: Dealing With null

Introduction

In Java, the keyword null is used to indicate that a variable or argument does not refer to a Java object.

The closest corresponding feature that C++ had to offer for a long time was NULL, which was used to represent a pointer that did not point anywhere (technically, a pointer to memory location 0). NULL was not even a first class language feature; instead, in most compilers, it was simply a preprocessor macro that stood for ((void*)0) or something similar.

C++11 introduced the nullptr keyword and the std::nullptr_t type to fill the same role in a more consistent fashion. The fact remains though, that NULL or nullptr can only be used with pointer types. Our proxy types don't use pointers to pass or return objects, so they cannot naturally be used with NULL or nullptr.

Enter xmog_null

We wanted you to be able to write C++ code that looks as much as possible like Java code and that meant that we had to get null working. To that effect we created a type called xmog_null that supports all operators that you would wish to use with null, i.e. equality and inequality comparison, and—in a nod to C/C++ coders—logical negation and conversion to bool.

Every compilation unit that includes the xmog_null.h header file receives a static xmog_null instance called null. You never have to explicitly deal with the xmog_null type or do anything special to gain access to null because it is included by every proxy type header.

This design allows you to write code like:

java::lang::String str = "test";

if( str == null ) {
    std::cerr << "This should never happen!" << std::endl;
}

try {
    if( str.equals( null ) ) {
        std::cerr << "We should not get here!" << std::endl;
    }
}
catch( NullPointerException npe ) {
}

As we discussed in the lesson on constructors, simply declaring a variable of a proxy type initializes it to Java null. Thus the following two declarations are identical in their outcome:

java::lang::String     str1;
java::lang::String     str2 = null;

assert( str1 == null );
assert( str2 == null );

We're mentioning this here again because it can be easy to forget that you can have a proxy instance that internally maintains a null reference. If you want to make sure that your proxy instance represents a Java object you have to compare it with null.

If you are an old C++ hand you will probably occasionally use NULL or nullptr by accident. This will cause compilation errors or unexpected behavior. Simply replace the offending instance with null and everything will work fine.