Java プログラマーにとって、null は頭痛の種です。 Null Pointer Exceptions (NPE) による嫌がらせを受けることがよくあります。 Java の発明者ですら、これは大きな間違いだったと認めています。 Java が null を保持するのはなぜですか? null はしばらく前から存在しており、null が解決する問題よりも多くの問題を引き起こすことを Java の発明者は知っていたと思いますが、null は依然として Java に存在します。
Java の設計原則は物事を単純化することなので、ポインターや演算子のオーバーロードに時間を無駄にすることはなく、多重継承の実装はその逆です。そうですね、この質問に対する答えはよくわかりませんが、わかっていることは、null が Java 開発者やオープンソース コミュニティからどれほど批判されても、私たちは null と共存しなければならないということです。 null の存在を後悔するのではなく、null についてよく学び、null が正しく使用されるようにする必要があります。
Java で null を学習する必要があるのはなぜですか?なぜなら、null に注意を払わないと、Java は NullPointerException に悩まされ、痛い教訓を学ぶことになるからです。エネルギッシュなプログラミングは、チーム、顧客、ユーザーがより高く評価する芸術です。私の経験では、null ポインター例外の主な理由の 1 つは、Java の null に関する知識が不十分であることです。多くの人はすでに null に精通していますが、そうでない人にとっても、null について古くて新しいことを学ぶことができます。 Java の null に関する重要な知識をもう一度学びましょう。
Java の Null とは何ですか?
先ほども述べたように、null は Java において非常に重要な概念です。 null の本来の目的は、欠落しているユーザー、リソース、その他のものなど、欠落しているものを表すことです。しかし、その 1 年後、厄介な null ポインタ例外が Java プログラマに多くの嫌がらせを引き起こしました。この資料では、Java の null キーワードの基本的な詳細を学び、null チェックを最小限に抑えるためのいくつかのテクニックと厄介な null ポインタ例外を回避する方法を検討します。
1)まず第一に、null は Java のキーワードであり、public、static、final と同様です。大文字と小文字が区別され、null を Null または NULL として記述することはできません。コンパイラはそれらを認識せず、エラーを報告します。
次のようにコードをコピーします。
オブジェクト obj = NULL // OK ではありません。
オブジェクト obj1 = null //OK
他の言語を使用しているプログラマーはこの問題を抱えている可能性がありますが、IDE を使用することでこの問題は簡単になりました。コードを入力すると、Eclipse や Netbeans などの IDE でこのエラーを修正できるようになりました。しかし、メモ帳、Vim、Emacs などの他のツールを使用すると、この問題は貴重な時間を無駄にすることになります。
2)すべてのプリミティブ型にはデフォルト値があるのと同様に、たとえば、int のデフォルト値は 0、boolean のデフォルト値は false、および null は参照型のデフォルト値です。厳密に言えば、これがデフォルト値です。すべてのオブジェクト タイプの。デフォルト値として false を持つブール変数を作成するのと同じように、Java の参照変数にはデフォルト値として null があります。これは、メンバー変数、ローカル変数、インスタンス変数、静的変数など、すべての変数に当てはまります (ただし、初期化されていないローカル変数を使用すると、コンパイラによって警告が表示されます)。この事実を実証するには、次のコードに示すように、変数を作成し、その値を出力することで、この参照変数を観察できます。
次のようにコードをコピーします。
プライベート静的オブジェクト myObj;
public static void main(String args[]){
System.out.println("myObjc の値は何ですか: " + myObj);
}
myObjc の値は何ですか: null
これは、静的オブジェクトと非静的オブジェクトの両方に当てはまります。ここでわかるように、myObj を静的参照として定義し、main メソッドで直接使用できるようにしました。 main メソッドは静的メソッドであるため、非静的変数は使用できないことに注意してください。
3) Null はオブジェクトでも型でもありません。null を任意の型に変換することもできます。
次のようにコードをコピーします。
String str = null // String には null を代入できます。
Integer itr = null // Integer に null を代入することもできます。
Double dbl = null // Double に null を代入することもできます。
String myStr = (String) null // null は String に型キャストできます。
Integer myItr = (Integer) null // Integer に型キャストすることもできます。
Double myDbl = (Double) null // 可能です、エラーはありません。
コンパイル時と実行時に null を任意の参照型にキャストでき、実行時に null ポインター例外がスローされないことがわかります。
4)参照変数には null を代入できますが、int、double、float、boolean などの基本型変数には null を代入できません。これを行うと、コンパイラは次のようなエラーをスローします。
次のようにコードをコピーします。
int i = null; // 型が一致しません: null から int に変換できません。
short s = null // 型が一致しません: null から short に変換できません。
byte b = null: // 型が一致しません: null からバイトに変換できません
double d = null //型が一致しません: null から double に変換できません。
整数 itr = null // これは問題ありません。
int j = itr; // これも問題ありませんが、実行時に NullPointerException が発生します。
ご覧のとおり、プリミティブ型に null を直接割り当てると、コンパイル エラーが発生します。ただし、ラッパー クラス オブジェクトに null を割り当ててから、それぞれの基本型にオブジェクトを割り当てた場合、コンパイラはそれを報告しませんが、実行時に null ポインター例外が発生します。これは Java での自動アンボックス化が原因で発生します。これについては次の箇条書きで説明します。
5) NULL 値を含むラッパー クラスは、Java がボックス化を解除して基本データ型を生成するときに、NULL ポインタ例外をスローします。一部のプログラマーは、オートボクシングによって null がそれぞれの基本型のデフォルト値 (int の場合は 0、boolean 型の場合は false など) に変換されると誤解しますが、それは正しくありません。以下に示します。
次のようにコードをコピーします。
整数 iAmNull = null;
int i = iAmNull; // コンパイル エラーがないことを覚えておいてください。
ただし、上記のコード スニペットを実行すると、メイン スレッドが null ポインタ例外をスローすることがコンソールに表示されます。このようなエラーの多くは、HashMap および Integer キー値を使用するときに発生します。次のコードを実行するとエラーが表示されます。
次のようにコードをコピーします。
java.util.HashMapをインポートします。
java.util.Mapをインポートします。
/**
※オートボクシングとNullPointerExceptionの例
*
* @author Windows 8
*/
パブリック クラス テスト {
public static void main(String args[]) throws InterruptedException {
マップ番号AndCount = new HashMap<>();
int[] 数値 = {3, 5, 7,9, 11, 13, 17, 19, 2, 3, 5, 33, 12, 5};
for(int i : 数値){
int カウント =numberAndCount.get(i);
numberAndCount.put(i, count++); // ここで NullPointerException が発生します。
}
}
}
出力:
次のようにコードをコピーします。
スレッド「メイン」での例外 java.lang.NullPointerException
Test.main(Test.java:25) で
このコードは非常にシンプルでエラーがないようです。行うべきことは、配列内に数値が何回出現するかを調べることだけです。これは、Java 配列で重複を見つけるための一般的な手法です。開発者は最初に前の値を取得し、次に値を追加し、最後にその値をマップに戻します。プログラマは、put メソッドを呼び出すときに、自動ボックス化によって int から Interger へのボックス化が処理されると考えているかもしれませんが、数値にカウント値がない場合、HashMap の get() メソッドは null と Not 0 を返すことを忘れています。なぜなら、Integer のデフォルト値は 0 ではなく null だからです。 null 値を int 変数に渡すと、オートボクシングは NullPointerException を返します。このコードが if ネスト内にあり、QA 環境では実行されていなかったとしても、実稼働環境に置くと、ドーンと動くことを想像してみてください :-)
6) null 値を持つ参照型変数が使用される場合、instanceof 操作は false を返します。
次のようにコードをコピーします。
整数 iAmNull = null;
if(iAmNull インスタンスオブ整数){
System.out.println("iAmNull は Integer のインスタンスです");
}それ以外{
System.out.println("iAmNull は Integer のインスタンスではありません");
}
出力:
次のようにコードをコピーします。
私
AmNull は Integer のインスタンスではありません
これは、instanceof 操作の非常に重要な機能であり、型キャスト チェックに役立ちます。
7) Null 値を持つ参照型変数を使用するために非静的メソッドを呼び出すことができないことはご存知かもしれません。 null ポインター例外がスローされますが、静的メソッドを使用して値が null の参照型変数を使用できることはご存知ないかもしれません。静的メソッドは静的バインディングを使用するため、null ポインター例外はスローされません。以下に例を示します。
次のようにコードをコピーします。
パブリック クラスのテスト {
public static void main(String args[]){
myObject = null; をテストしています。
myObject.iAmStaticMethod();
myObject.iAmNonStaticMethod();
}
プライベート静的 void iAmStaticMethod(){
System.out.println("私は静的メソッドなので、null 参照によって呼び出すことができます");
}
private void iAmNonStaticMethod(){
System.out.println("私は静的メソッドではないので、null で呼び出す必要はありません");
}
出力:
次のようにコードをコピーします。
私は静的メソッドなので、null 参照によって呼び出すことができます
スレッド「メイン」での例外 java.lang.NullPointerException
Testing.main(Testing.java:11) で
8)メソッドに null を渡すことができ、メソッドは任意の参照型を受け取ることができます。たとえば、public void print(Object obj) は次のように print(null) を呼び出すことができます。これはコンパイルの観点からは問題ありませんが、結果はメソッドに完全に依存します。この例の print メソッドなどの Null セーフ メソッドは、NullPointerException をスローせず、単に正常に終了します。ビジネス ロジックが許可する場合は、null セーフ メソッドを使用することをお勧めします。
9) == または != 演算を使用して NULL 値を比較できますが、他のアルゴリズムや論理演算 (「未満」または「より大きい」など) は使用できません。 SQL とは異なり、以下に示すように、Java では null==null は true を返します。
次のようにコードをコピーします。
パブリック クラス テスト {
public static void main(String args[]) throws InterruptedException {
文字列 abc = null;
文字列 cde = null;
if(abc == cde){
System.out.println("null == null は Java では true");
}
if(null != null){
System.out.println("null != Java では null は false");
}
// 古典的な null チェック
if(abc==null){
// 何かをする
}
// ダメです、コンパイル時エラーです
if(abc > null){
}
}
}
出力:
次のようにコードをコピーします。
null == null は Java では true
これはすべて Java の null に関するものです。 Java プログラミングの経験があり、NULL ポインター例外を回避する簡単なトリックを使用すれば、コードを NULL セーフにすることができます。 null は空の値または初期化されていない値としてよく使用されるため、混乱の原因となります。メソッドの場合、null がパラメータとして使用されたときにメソッドがどのように動作するかを記録することも非常に重要です。全体として、null は参照型変数のデフォルト値であることに注意してください。Java では、null 参照を使用してインスタンス メソッドやインスタンス変数を呼び出すことはできません。