You've slightly misunderstood that documentation.
The documentation for the logical and operator
&& says that in the expression
x && y, neither x nor y can be null.
However, there is a difference between being null and checking for null.
a != null and
a.Id != null are both expressions that return boolean values. These expressions can have null appear in them without issue. The only time you'd run into a problem here is if you were to check
a.Id != null before checking if
a is null.
a is null, the expression fragment
a.Id would translate to
null.Id, and you'd get a null pointer exception.
Battery.cord's and Jesse Milburn's comments on short circuit evaluation are also good to keep in mind. The reason why this null-checking pattern works is because of short-circuit evaluation.
a is null, then your expression becomes
if(false && a.Id != null). From Boolean logic/algebra,
false && x == false. There becomes no need to evaluate the second part of your expression, so Salesforce doesn't evaluate it.
if(a != null && a.Id != null) is perfectly legal.