108

次のコードがスローされNullPointerExceptionます:

int num = Integer.getInteger("123");

getInteger静的なので、コンパイラはnullを呼び出していますか?それは意味がありません!

何が起こっていますか?

4

3 に答える 3

218

大きな絵

ここでは2つの問題があります。

  • Integer getInteger(String)あなたが思っていることをしません
    • nullこの場合は戻ります
  • Integerからの割り当てintにより、自動開開 が発生します
    • なので、スローされIntegerますnullNullPointerException

に解析(String) "123"するに(int) 123は、たとえばを使用できますint Integer.parseInt(String)

参考文献

IntegerAPIリファレンス


の上Integer.getInteger

このメソッドの機能について、ドキュメントに記載されている内容は次のとおりです。

public static Integer getInteger(String nm):指定された名前のシステムプロパティの整数値を決定します。指定された名前のプロパティがない場合、指定された名前が空またはnullである場合、またはプロパティの数値形式が正しくない場合は、nullが返されます。

つまり、このメソッドはaStringint/Integer値に解析することとは関係がなく、むしろSystem.getPropertyメソッドと関係があります。

確かに、これは非常に驚きです。ライブラリにこのような驚きがあるのは残念ですが、それは貴重な教訓を教えてくれます。常にドキュメントを調べて、メソッドが何をするかを確認してください。

偶然にも、この問題のバリエーションは、パズルのリターン:Schlock and Awe(TS-5186)、Josh Bloch、NealGafterの2009JavaOneテクニカルセッションのプレゼンテーションで取り上げられました。最後のスライドは次のとおりです。

道徳

  • 奇妙でひどい方法が図書館に潜んでいる
    • いくつかは無害な響きの名前を持っています
  • コードが誤動作した場合
    • 適切なメソッドを呼び出していることを確認してください
    • ライブラリのドキュメントを読む
  • APIデザイナー向け
    • 驚き最小の原則に違反しないでください
    • 抽象化階層に違反しないでください
    • 大きく異なる動作に類似した名前を使用しないでください

完全を期すために、次のような方法もありますInteger.getInteger

関連する質問


自動アンボックスについて

もちろん、もう1つの問題は、がどのようNullPointerExceptionにスローされるかです。この問題に焦点を当てるために、次のようにスニペットを簡略化できます。

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!

これは、Effective Java 2nd Edition、アイテム49からの引用です。ボックス化されたプリミティブよりもプリミティブ型を優先します。

要約すると、選択できる場合は常に、ボックス化されたプリミティブよりもプリミティブを使用します。プリミティブ型はより単純で高速です。ボックス化されたプリミティブを使用する必要がある場合は、注意してください。自動ボクシングは、ボックス化されたプリミティブを使用する際の冗長性を軽減しますが、危険性は軽減しません。プログラムが2つのボックス化されたプリミティブを==演算子と比較するとき、それはID比較を行いますが、これはほぼ確実にあなたが望むものではありません。プログラムがボックス化されたプリミティブとボックス化されていないプリミティブを含む混合型の計算を行う場合、プログラムはボックス化解除を行い、プログラムがボックス化解除を行う場合、をスローする可能性がありNullPointerExceptionます。最後に、プログラムがプリミティブ値をボックス化すると、コストがかかり、不要なオブジェクトが作成される可能性があります。

ジェネリックなど、ボックス化されたプリミティブを使用せざるを得ない場所もありますが、それ以外の場合は、ボックス化されたプリミティブを使用する決定が正当化されるかどうかを真剣に検討する必要があります。

関連する質問

于 2010-06-26T09:18:53.493 に答える
17

http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.htmlから:

getInteger'指定された名前のシステムプロパティの整数値を決定します。

あなたはこれを求めている:

Integer.parseInt("123")
于 2010-06-26T09:20:36.173 に答える
6

getInteger()メソッドのドキュメントを確認してください。このメソッドでは、Stringパラメーターは、指定された名前のシステムプロパティの整数値を決定するシステムプロパティです。ここで説明するように、「123」はシステムプロパティの名前ではありません。この文字列をに変換する場合intは、メソッドをとして使用し int num = Integer.parseInt("123")ます。

于 2010-06-26T09:43:53.047 に答える