Let's take a look at the following code to check if such an object is empty:
If (someobject! = Null ){
Someobject. doCalc ();
}
To avoid null pointer exceptions, nothing seems inappropriate. However, it is really difficult to judge whether an object in the code is empty.
Whether the object is a null contract
When defining APIs, we usually follow some rules, which can be called conventions, such as interfaces:
Public Set <String> getCollections ();
In general, or without special instructions, the returned set cannot be null. If there is no element, it should be an EmptySet. The upstream and downstream interfaces comply with such conventions, so some defensive code can be saved. Strictly speaking, whether the returned result is null should be included in the API documentation. When the returned result is null, you must declare its special meaning. The object is empty and can often express special meanings:
Public void updateUser (User user );
For example, to update the user information, the user has an attribute age of the type Integer. If it is null, this attribute is ignored and not updated. If you use an int of the primitive type, you need to use a special value. It is natural that there is no Integer.
Improvement in other languages
In Groovy, the syntax sugar such as the question mark makes the logic of empty code most simplified:
Def streetName = user ?. Address ?. Street
In the above code, if the user is empty, it will not access its address member. If the address is empty, it will not access street.
In Objective C, a method call becomes a message transmission mechanism. When a message is sent to nil, no side effects occur except that 0 is returned. There are four types of Objective C:
NULL is a NULL pointer from the C language; nil is an object pointing to NULL; Nil is similar to nil, but it is a class pointing to NULL; NSNull is used to solve the problem that a set element cannot be empty. It is equivalent to a pack of empty elements and represents an empty element in the set.
Scala has an Option abstract class, which is strongly typed, that is, Option [T]. Once defined, this type cannot be changed. It has two subclasses, Some and None. None is an empty Singleton object, and Some stores the actual results:
Def show (x: Option [String]) = x match {
Case Some (s) => s
Case None => "? "
}
The object is empty during compilation.
In JSR 305: Annotations for Software Defect Detection, it was initially inspired by FindBug and IntelliJ. To put it bluntly, there are two Annotations: @ NonNull and @ CheckForNull:
If such a method is defined:
Void someMethod (@ NotNull someParameter ){}
Then, during the call, such code will directly fail to be compiled:
SomeMethod (null );
Otherwise, define the method as follows:
@ Nullable iWantToDestroyEverything () {return null ;}
In this way, unchecked method calls will also fail during compilation:
1
IWantToDestroyEverything (). something ();
That is to say, the potential NPE problems are identified during the compilation time.
Empty object check
You do not need to write defensive judgment statements to process empty objects. For example, the Objects object of JDK 7:
This. child = Objects. requireNonNull (child, "it is empty ");
This completes the value assignment statement when the object is not empty. If the object is empty, an exception with the message "it is empty" is thrown.
The Jarkata Commons API also provides a method to check whether the object is empty. Alternatively, you can use the Java Native assert keyword.
NPE is also popular
For example:
Public Photo getGirlfriendPhoto (){
Try {
Return appContext. getPhotoDataSource (). getPhotoByName (me. getGirlfriend (). getName ());
} Catch (NullPointerException e ){
Return null;
}
}
To avoid NPE, you may write code similar to this:
Public Photo getGirlfriendPhoto (){
If (appContext! = Null ){
If (appContext. getPhotoDataSource ()! = Null ){
If (me! = Null ){
If (me. getGirlfriend ()! = Null ){
If (me. getGirlfriend (). getName ()! = Null ){
// Finally we are arrived
Return appContext. getPhotoDataSource (). getPhotoByName (me. getGirlfriend (). getName ());
}
}
}
}
}
Return null;
}