web-dev-qa-db-ja.com

Nullオブジェクトをプリミティブ型にアンボックス化すると、NullPointerExceptionが発生します。

このスニペットは、プリミティブ型にボックス化解除され、Long.longValue()が呼び出されるため、NullPointerExceptionをスローします。

これは、次のようなスニペットがあるかどうかさえ簡単にわかります。

long value = (Long) null;

しかし、NullPointerExceptionは、次のような複雑な状況になるとさらに困難になります。

long propertyValue = (Long) obj.getProperty(propertyModel.getName());

それで、Javaコンパイラーがこれからより快適な例外を作成する可能性はありませんか?私はIllegalArgumentExceptionのようなメッセージを希望します"nullオブジェクトをプリミティブ型にキャストしようとしていますが、これは実行できません!"

これはもっと適切ではないでしょうか?どう思いますか?これは実行時にも可能ですか?このキャストを特定できますか? Javaバイトコードをまだ確認していません。ソリューションで使用できるかもしれません。

この質問には答えることができます:この動作を達成できるかどうか知りたい!

39

Java言語仕様 によると、Number.longValue()Number.intValue()などを呼び出すことでボックス化解除が行われます。特別なバイトコードのマジックは行われません。これらのメソッドを手動で呼び出す場合。したがって、NullPointerExceptionnullのボックス化解除の自然な結果です(実際にはJLSによって義務付けられています)。

別の例外をスローするには、アンボクシング変換のたびにnulltwiceをチェックする必要があります(特別な例外をスローするかどうかを決定するために、一度、メソッドが実際に呼び出されたときに暗黙的に)。言語デザイナーはそれを正当化するのに十分便利だとは思わなかったと思います。

75

Java 8 SEなので、Optional.ofNullableもあります。

long value = Optional.ofNullable(obj.getProperty(propertyModel.getName())).orElse(0L)));
15
oluies

このような場合には、小さなプライベートヘルパーを作成することをお勧めします。これらは、正しいキャスト、エラーメッセージ、デフォルト値の生成を処理できます。

操作の十分な「状態」を例外に含めることをお勧めします(この場合、オプション名と値-見つからない場合はオプションマップの文字列表現も)。

何かのようなもの:

private long safeGetLong(Map<String, Option> options, String name) {
  if (name == null || options == null)
    throw new IllegalArgumentExcption("You need to give options and name. (name="+name+", opts=" + options));
  Object val = options.get(name);
  if (val == null)
    throw new ConfigurationException("The option name="+name+" is unknown");
  if (val instanceof Long)
    return val.longValue();

  String strVal = null;
  try
  {
    strVal = val.toString();
    return Long.parseValue(strVal);
  } catch (Exception ex) {
    throw new ConfigurationException("Cannot parse " + name + "=" + strVal + " into a Long.");
  }
}

もちろん、型指定されたアクセスを許可する設定オブジェクトを持つことはさらに良いです。

あなたのためにそれを行うことができるいくつかの検証フレームワークがありますが、問題のアプリケーションのIN8Lと例外階層またはロギング規則によりよく適合するので、私は通常自分でコードを書くことになります。それをジェネリックにするのは難しい。

1
eckes

それはIllegalArgumentExceptionが意味するものではありません。コンパイラーは、実行時まで値がnullであることを保証しません。それが知っているすべてはあなたの例ではStringである可能性が高いタイプです。

確かに実行時に例外がスローされると、コンパイラーは問題がnull値であることを認識します。デバッガを使用している場合は、これを自分で確認できます。テクノロジーの観点から-そして、これがあなたの質問への短い回答です-はい、それは可能ですエラーの説明にそれを含めるコンパイラを作成します。しかし、nullの値に関する特別なメッセージが必要な場合は、次はどうしますか? 10を超える許容範囲外の整数の特別なメッセージ?確かにそれはばかげた例のようなものですが、それが実例となることを願っています。

1
Pops