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.