ホームページ >Java >&#&チュートリアル >JavaのNullについて知っておくべき9つのこと

JavaのNullについて知っておくべき9つのこと

伊谢尔伦
伊谢尔伦オリジナル
2016-11-26 09:38:271246ブラウズ

Java プログラマーにとって、null は頭痛の種です。 Null Pointer Exceptions (NPE) による嫌がらせを受けることがよくあります。 Java の発明者ですら、これは大きな間違いだったと認めています。 Java が null を保持するのはなぜですか? null はしばらく前から存在しており、null が解決する問題よりも多くの問題を引き起こすことを Java の発明者は知っていたと思いますが、null は依然として Java に存在します。

JavaのNullについて知っておくべき9つのこと


Java の設計原則は物事を単純化することなので、ポインター、演算子のオーバーロード、多重継承の実装に時間を無駄にすることはありませんが、null はその逆です。 。そうですね、この質問に対する答えはよくわかりませんが、わかっていることは、null が Java 開発者やオープンソース コミュニティからどれほど批判されても、私たちは null と共存しなければならないということです。 null の存在を後悔するのではなく、null についてよく学び、null が正しく使用されるようにする必要があります。

なぜJavaでnullを学ぶ必要があるのでしょうか?なぜなら、null に注意を払わないと、Java は NullPointerException に悩まされ、痛い教訓を学ぶことになるからです。エネルギッシュなプログラミングは、チーム、顧客、ユーザーがより高く評価する芸術です。私の経験では、null ポインター例外の主な理由の 1 つは、Java の null に関する知識が不十分であることです。多くの人はすでに null に精通していますが、そうでない人にとっても、null について古くて新しいことを学ぶことができます。 Java の null に関する重要な知識をもう一度学びましょう。

JavaのNullとは何ですか?

先ほども言いましたが、Java では null は非常に重要な概念です。 null の本来の目的は、欠落しているユーザー、リソース、その他のものなど、欠落しているものを表すことです。しかし、その 1 年後、厄介な null ポインタ例外が Java プログラマに多くの嫌がらせを引き起こしました。この資料では、Java の null キーワードの基本的な詳細を学び、null チェックを最小限に抑えるためのいくつかのテクニックと厄介な null ポインタ例外を回避する方法を検討します。

1) まず、nullはJavaではpublic、static、finalと同じキーワードです。大文字と小文字が区別され、null を Null または NULL として記述することはできません。コンパイラはそれらを認識せず、エラーを報告します。

Object obj = NULL; // Not Ok
Object obj1 = null  //Ok

他の言語を使用しているプログラマーはこの問題を抱えているかもしれませんが、今では IDE を使用することでこの問題は簡単になりました。コードを入力すると、Eclipse や Netbeans などの IDE でこのエラーを修正できるようになりました。しかし、メモ帳、Vim、Emacs などの他のツールを使用すると、この問題は貴重な時間を無駄にすることになります。

2) すべてのプリミティブ型にデフォルト値があるのと同じように、int のデフォルト値は 0、boolean のデフォルト値は false、null は参照型のデフォルト値であり、大まかに言えば、それがデフォルト値です。すべてのオブジェクト タイプの。デフォルト値として false を持つブール変数を作成するのと同じように、Java の参照変数にはデフォルト値として null があります。これは、メンバー変数、ローカル変数、インスタンス変数、静的変数など、すべての変数に当てはまります (ただし、初期化されていないローカル変数を使用すると、コンパイラによって警告が表示されます)。この事実を実証するには、次のコードに示すように、変数を作成し、その値を出力することで参照変数を観察できます。

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

これは、静的オブジェクトと非静的オブジェクトの両方に当てはまります。ここでわかるように、myObj を静的参照として定義し、main メソッドで直接使用できるようにしました。 main メソッドは静的メソッドであるため、非静的変数は使用できないことに注意してください。

3) Null はオブジェクトでも型でもありません。null を任意の型に変換することもできます。 :

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

コンパイル時と実行時に null を任意の参照型にキャストでき、実行時に null ポインター例外がスローされないことがわかります。

4) 参照変数にはnullを代入できますが、int、double、float、booleanなどの基本型変数にはnullを代入できません。これを行うと、コンパイラは次のようなエラーを報告します:

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

ご覧のとおり、基本型に null を直接代入すると、コンパイル エラーが発生します。ただし、ラッパー クラス オブジェクトに null を割り当ててから、それぞれの基本型にオブジェクトを割り当てた場合、コンパイラはそれを報告しませんが、実行時に null ポインター例外が発生します。これは Java での自動アンボックス化が原因で発生します。これについては次の箇条書きで説明します。

  5) 任何含有null值的包装类在Java拆箱生成基本数据类型时候都会抛出一个空指针异常。一些程序员犯这样的错误,他们认为自动装箱会将null转换成各自基本类型的默认值,例如对于int转换成0,布尔类型转换成false,但是那是不正确的,如下面所示:

Integer iAmNull = null;
int i = iAmNull; // Remember - No Compilation Error

  但是当你运行上面的代码片段的时候,你会在控制台上看到主线程抛出空指针异常。在使用HashMap和Integer键值的时候会发生很多这样的错误。当你运行下面代码的时候就会出现错误。

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
      }       
    }
}

  输出:

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:

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");
}

  输出:

i
AmNull is NOT an instance of Integer

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

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

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&#39;t date to call me by null");
   }

  输出:

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,如下所示:

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){
       }
    }
}

  输出:

null == null is true in Java

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


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。