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.