int num = Integer.getInteger(“ 123”)がNullPointerExceptionをスローするのはなぜですか?


106

次のコードがスローしNullPointerExceptionます。

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

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

何が起こっていますか?


3
代わりにInteger.getValue()を使用してください。:このブログの記事は良い、について説明する理由である konigsberg.blogspot.in/2008/04/...
Pranaysharma

回答:


212

大きな絵

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

  • Integer getInteger(String) あなたが思っていることをしていません
    • nullこの場合は戻る
  • Integertoへの割り当ては、int自動アンボックス化を引き起こします
    • 以来IntegerされnullNullPointerExceptionスローされます

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

参考文献

Integer APIリファレンス


オン Integer.getInteger

このメソッドが何をするかについてのドキュメントの説明は次のとおりです。

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

つまり、このメソッドはa Stringint/Integer値に解析することとは関係ありませんが、メソッドと関係がありますSystem.getProperty

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

偶然にも、この問題のバリエーションがReturn of the Puzzlers:Schlock and Awe(TS-5186)、Josh BlochとNeal Gafterの2009 JavaOne Technical Sessionプレゼンテーションで紹介されました。これが最後のスライドです。

道徳

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

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

関連する質問


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

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

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

これは、Effective Java 2nd Edition、Item 49:Preferプリミティブ型よりボックス化されたプリミティブからの引用です。

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

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

関連する質問


11
だからInteger.getInteger(s)大体同じInteger.parseInt(System.getProperty(s))ですか?2番目の方がより詳細ですが、システムプロパティから情報を取得しているという事実を強調するので、2番目の方が好きだと思います。
MatrixFrog

5
そのコメントを投稿するとすぐに、Integerクラスの実際のソースを見るだけでよいことに気付きました。私は正しい軌道に乗っていましたが、のInteger.decode代わりにを使用Integer.parseIntして、先頭を検索し0xたり0、数値をそれぞれ16進数または8進数として解析したりしました。
MatrixFrog 2010年

なぜNullPointerException質問している人のためにprogrammers.stackexchange.com/questions/158908/...
ROMANIA_engineer

2
@Oracleはjava.lang.Integer.getInteger(String)を非推奨にできますか?
mjaggard 2018年


6

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.