Java で NullPointerException を適切に回避する
-
12-09-2019 - |
質問
次の行を考えてみましょう。
if (object.getAttribute("someAttr").equals("true")) { // ....
明らかに、この行は潜在的なバグです。属性は次のとおりである可能性があります。 null
そして私たちは NullPointerException
. 。したがって、次の 2 つの選択肢のいずれかにリファクタリングする必要があります。
最初のオプション:
if ("true".equals(object.getAttribute("someAttr"))) { // ....
2 番目のオプション:
String attr = object.getAttribute("someAttr");
if (attr != null) {
if (attr.equals("true")) { // ....
最初のオプションは読みにくいですが、より簡潔です。一方、2 番目のオプションは意図は明らかですが、冗長です。
読みやすさの観点からどのオプションが好みですか?
解決
いつも使っています
if ("true".equals(object.getAttribute("someAttr"))) { // ....
読むのは少し難しいですが、冗長ではなく、十分読みやすいと思うので、すぐに慣れることができます。
他のヒント
2 番目のオプションでは、短絡を利用できます。 &&
:
String attr = object.getAttribute("someAttr");
if (attr != null && attr.equals("true")) { // ....
簡潔なアプローチが最初は間違っているように感じられる特定の状況がありますが、効果的には になる 慣用的な。これもその 1 つです。もう1つは次のようなものです:
String line;
while ((line = bufferedReader.readLine()) != null) {
// Use line
}
ある状態での副作用?考えられない!ただし、特定のパターンを認識した場合、基本的に代替案よりも優れています。
このパターンも似ています。Java では非常に一般的なので、ある程度経験のある開発者なら認識できると思います。結果は心地よい簡潔さです。(面白いことに、同じイディオムを不必要に使用する C# コードを時々見かけます。C# では等価演算子が文字列で正常に機能します。)
結論:最初のバージョンを使用して、それに慣れてください。
私は選択肢 1 が気に入っており、十分読みやすいと思います。
ちなみにオプション 3 は、デフォルト値をパラメータとして受け取る getAttribute メソッドを導入することです。
どちらも機能的に同等であることを考慮して、常に短いコードを目指してください。特に今回のような可読性が犠牲にされない場合には。
Util.isEmpty(string)
- 戻り値 string == null || string.trim().isEmpty()
Util.notNull(string)
の場合は「」を返します string == null
, 、それ以外の場合は文字列。Util.isNotEmpty(string)
戻り値 ! Util.isEmpty(string)
文字列については、次のような規則があります。 Util.isEmpty(string)
意味的には真を意味し、 Util.isNotEmpty(string)
意味的には偽を意味します。
とても良い質問ですね。私は通常、優雅ではないものを使用します。
if (object.getAttribute("someAttr") != null && object.getAttribute("someAttr").equals("true")) { // ....
(そしてもう使わない)
私には別の答えがあります。
List<Map<String, Object>> group = jjDatabase.separateRow(db.Select("SELECT * FROM access_user_group WHERE user_id=1 ;"));
私のデータベースには「access_user_group」の列として「group_c80」がないため、get(0).get("group_c80") で null ポインタ例外が一致します。しかし、私は以下のコードを通じてそれを処理しました:
for (int j = 1; j < 100; j++) {
String rulId="0";//defult value,to privent null pointer exeption in group_c
try {
rulId = group.get(0).get("group_c" + j)).toString();
} catch (Exception ex) {
ServerLog.Print( "Handeled error in database for " + "group_c" + (j < 10 ? "0" + j : j) +"This error handeled and mot efect in program");
rulId = "0";
}}
これが私のアプローチです。 PropertyUtil
ただし、クラスは一度しか書かれていません:
/**
* Generic method to encapsulate type casting and preventing nullPointers.
*
* @param <T> The Type expected from the result value.
* @param o The object to cast.
* @param typedDefault The default value, should be of Type T.
*
* @return Type casted o, of default.
*/
public static <T> T getOrDefault (Object o, T typedDefault) {
if (null == o) {
return typedDefault;
}
return (T) o;
}
クライアントコードはこれを行うことができます:
PropertyUtil.getOrDefault(obj.getAttribute("someAttr"), "").equals("true");
または、リストの場合:
PropertyUtil.getOrDefault(
genericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST
).contains(element);
または、List のコンシューマに対しては、Object が拒否されます。
consumeOnlyList(
PropertyUtil.getOrDefault(
enericObjectMap.get(MY_LIST_KEY), Collections.EMPTY_LIST
)
)
デフォルトは null オブジェクト パターンの impl である可能性があります https://en.wikipedia.org/wiki/Null_Object_pattern