Things null must know

 This article was translated from  javarevisited by  ImportNew  -  Calarence . Welcome to the translation team . For reprint, please see the requirements at the end of the article.

For Java programmers, null is a headache. It is often harassed by Null Pointer Exception (NPE). Even the inventor of Java admits it was a huge mistake. Why does Java keep null? null has been around for a while, and I think the Java inventors knew that null caused more trouble than the problem it solved, but null is still with Java.

I am more and more amazed because java is designed to simplify things and that's why no time is wasted on pointers, operator overloading, multiple inheritance implementations, null is the exact opposite. Well, I don't really know the answer to this question, what I do know is that we have to live with null no matter how it gets criticized by Java developers and the open source community. Instead of regretting the existence of null, we might as well learn about null and make sure to use it correctly.

Why do you need to learn null in Java? Because if you don't pay attention to null, Java will make you suffer from null pointer exceptions, and you will learn a hard lesson. Energetic programming is an art, and your team, clients, and users will appreciate you even more. In my experience, one of the main causes of null pointer exceptions is not enough knowledge about null in Java. Many of you are already familiar with null, but for those who are not, there is something old and new to learn about null. Let's relearn some important things about null in Java.

What is Null in Java?

As I said, null is a very important concept in Java. null was originally designed to represent something missing, such as a missing user, resource, or something else. However, a year later, the troublesome null pointer exception brought a lot of harassment to Java programmers. In this material, we'll learn the basics of the null keyword in Java, and explore techniques to minimize null checks and avoid nasty null pointer exceptions.

1) First of all, null is a keyword in Java, like public, static, final. It's case sensitive, you can't write null as Null or NULL, the compiler won't recognize them and throw an error.

1
2
Object obj = NULL; // Not Ok
Object obj1 = null  //Ok
Programmers using other languages ​​may have this problem, but now the use of IDEs has made this problem trivial. Now, when you type code, IDEs like Eclipse, Netbeans can correct this error. But with other tools like notepad, Vim, Emacs, this problem will waste your precious time.

2) Just like every primitive type has a default value, such as the default value of int is 0, the default value of boolean is false, and null is the default value of any reference type, not strictly speaking, the default value of all object types. Just like you create a variable of type boolean that has false as its own default value, any reference variable in Java has null as its default value. This is true for all variables, such as member variables, local variables , instance variables, static variables (but the compiler will warn you when you use an uninitialized local variable). To prove this fact, you can observe the reference variable by creating a variable and then printing its value, as shown in the code below:

1
2
3
4
private static Object myObj;
public static void main(String args[]){
     System.out.println( "What is value of myObjc : " + myObj);
}
1
What is value of myObjc : null

This is true for both static and non-static objects. As you can see here, I defined myObj as a static reference, so I can use it directly in the main method. Note that the main method is a static method and cannot use non-static variables.

3) We want to clarify some misunderstandings, null is neither an object nor a type, it is just a special value, you can assign it to any reference type, you can also convert null to any type , see the following Code:

1
2
3
4
5
6
7
String str = null ; // null can be assigned to String
Integer itr = null ; // you can assign null to Integer also
Double dbl = null // null can also be assigned to Double
 
String myStr = (String) null ; // null can be type cast to String
Integer myItr = (Integer) null ; // it can also be type casted to Integer
Double myDbl = (Double) null ; // yes it's possible, no error
You can see that casting null to any reference type works at compile time and runtime, without throwing a null pointer exception at runtime.

4) Null can be assigned to reference variables, you cannot assign null to basic type variables, such as int, double, float, boolean. If you do that, the compiler will report an error like this:

1
2
3
4
5
6
7
int i = null ; // type mismatch : cannot convert from null to int
short s = null ; //  type mismatch : cannot convert from null to short
byte b = null : // type mismatch : cannot convert from null to byte
double d = null ; //type mismatch : cannot convert from null to double
 
Integer itr = null ; // this is ok
int j = itr; // this is also ok, but NullPointerException at runtime
As you can see, when you assign null directly to the base type, you get a compile error. But if you assign null to the wrapper class object, and then assign the object to the respective base type, the compiler will not report it, but you will encounter a null pointer exception at runtime. This is caused by automatic unboxing in Java, which we will see in the next bullet point.

5) Any wrapper class with a null value will throw a null pointer exception when Java unboxes the primitive data type. Some programmers make the mistake of thinking that autoboxing will convert null to the default value of their respective base type , e.g. 0 for int and false for boolean, but that's not true, as shown below:

1
2
Integer iAmNull = null ;
int i = iAmNull; // Remember - No Compilation Error
But when you run the above code snippet, you will see on the console that the main thread throws a null pointer exception. Many of these errors occur when using HashMap and Integer keys. An error occurs when you run the code below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.HashMap;
import java.util.Map;
 
/**
  * An example of Autoboxing and NullPointerExcpetion
  *
  * @author WINDOWS 8
  */
public class Test {
     public static void main(String args[]) throws InterruptedException {
       Map numberAndCount = new HashMap<>();
       int [] numbers = { 3 , 5 , 7 , 9 , 11 , 13 , 17 , 19 , 2 , 3 , 5 , 33 , 12 , 5 };
 
       for ( int i : numbers){
          int count = numberAndCount.get(i);
          numberAndCount.put(i, count++); // NullPointerException here
       }      
     }
}

output:

1
2
Exception in thread "main" java.lang.NullPointerException
  at Test.main(Test.java:25)

这段代码看起来非常简单并且没有错误。你所做的一切是找到一个数字在数组中出现了多少次,这是Java数组中典型的寻找重复的技术。开发者首先得到以前的数值,然后再加一,最后把值放回Map里。程序员可能会以为,调用put方法时,自动装箱会自己处理好将int装箱成Interger,但是他忘记了当一个数字没有计数值的时候,HashMap的get()方法将会返回null,而不是0,因为Integer的默认值是null而不是0。当把null值传递给一个int型变量的时候自动装箱将会返回空指针异常。设想一下,如果这段代码在一个if嵌套里,没有在QA环境下运行,但是你一旦放在生产环境里,BOOM:-)

6)如果使用了带有null值的引用类型变量,instanceof操作将会返回false:

1
2
3
4
5
6
7
Integer iAmNull = null ;
if (iAmNull instanceof Integer){
    System.out.println( "iAmNull is instance of Integer" );                            
 
} else {
    System.out.println( "iAmNull is NOT an instance of Integer" );
}

输出:

1
i
1
AmNull is NOT an instance of Integer

这是instanceof操作一个很重要的特性,使得对类型强制转换检查很有用

7)你可能知道不能调用非静态方法来使用一个值为null的引用类型变量。它将会抛出空指针异常,但是你可能不知道,你可以使用静态方法来使用一个值为null的引用类型变量。因为静态方法使用静态绑定,不会抛出空指针异常。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Testing {            
    public static void main(String args[]){
       Testing myObject = null ;
       myObject.iAmStaticMethod();
       myObject.iAmNonStaticMethod();                            
    }
 
    private static void iAmStaticMethod(){
         System.out.println( "I am static method, can be called by null reference" );
    }
 
    private void iAmNonStaticMethod(){
        System.out.println( "I am NON static method, don't date to call me by null" );
    }

输出:

1
2
3
I am static method, can be called by null reference
Exception in thread "main" java.lang.NullPointerException
                at Testing.main(Testing.java:11)

8)你可以将null传递给方法使用,这时方法可以接收任何引用类型,例如public void print(Object obj)可以这样调用print(null)。从编译角度来看这是可以的,但结果完全取决于方法。Null安全的方法,如在这个例子中的print方法,不会抛出空指针异常,只是优雅的退出。如果业务逻辑允许的话,推荐使用null安全的方法。

9)你可以使用==或者!=操作来比较null值,但是不能使用其他算法或者逻辑操作,例如小于或者大于。跟SQL不一样,在Java中null==null将返回true,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test {
 
     public static void main(String args[]) throws InterruptedException {
 
        String abc = null ;
        String cde = null ;
 
        if (abc == cde){
            System.out.println( "null == null is true in Java" );
        }
 
        if ( null != null ){
            System.out.println( "null != null is false in Java" );
        }
 
        // classical null check
        if (abc == null ){
            // do something
        }
 
        // not ok, compile time error
        if (abc > null ){
 
        }
     }
}

输出:

1
null == null is true in Java

这是关于Java中null的全部。通过Java编程的一些经验和使用简单的技巧来避免空指针异常,你可以使你的代码变得null安全。因为null经常作为空或者未初始化的值,它是困惑的源头。对于方法而言,记录下null作为参数时方法有什么样的行为也是非常重要的。总而言之,记住,null是任何一个引用类型变量的默认值,在java中你不能使用null引用来调用任何的instance方法或者instance变量。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325295967&siteId=291194637