質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

例外処理

例外処理(Exception handling)とは、プログラム実行中に異常が発生した場合、通常フローから外れ、例外として別の処理を行うようにデザインされたプログラミング言語構造です。

Q&A

解決済

6回答

13156閲覧

効率的な値の初期化はどうすればよいか

退会済みユーザー

退会済みユーザー

総合スコア0

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

例外処理

例外処理(Exception handling)とは、プログラム実行中に異常が発生した場合、通常フローから外れ、例外として別の処理を行うようにデザインされたプログラミング言語構造です。

0グッド

0クリップ

投稿2016/04/08 14:58

編集2016/04/12 10:36

###値の初期化について
オブジェクトなどに値をセットするとき、
その値の初期化について、知恵をお貸しいただきたいです。

例えば次のようなコード(例1)

Java

1Dto dto = new Dto(); 2List<String> eggs= new ArrayList<String>(); 3 4try{ 5 Spam spam = hoge.fuga(); 6 if(spam.getHam() != null && spam.getHam().getEggs() != null){ 7 eggs = spam.getHam().getEggs(); 8 } 9}catch(Exception e){ 10 // 例外処理 11} 12 13dto.setEggs(eggs);

上のコードは下のようにも書き換え可能です(例2)。

Java

1Dto dto = new Dto(); 2List<String> eggs; 3 4try{ 5 Spam spam = hoge.fuga(); 6 if(spam.getHam() != null && spam.getHam().getEggs() != null){ 7 eggs = spam.getHam().getEggs(); 8 }else{ 9 eggs = new ArrayList<String>(); 10 } 11}catch(Exception e){ 12 eggs = new ArrayList<String>(); 13 // 例外処理 14} 15 16dto.setEggs(eggs);

dtoにセットするeggsはnullではなく、必ずListのインスタンスではいけないとき
次のことが気になっています。

###問題(気になること)

  • 例1について

割りとスッキリかけているとは思いますが、必ずeggsにインスタンスを代入するので、
eggsが取得できた場合に無駄かなと感じてしまいます。

  • 例2について

例1とは反対に無駄な代入はありませんが、その分elseやcatch時に処理が追加されてしまい、
可読性は下がってしまうのかなと感じてしまいます。

自分の考えとしては、spamからeggsが取得できる確率や例外の発生頻度などを考慮して、
使い分けるしかないのかなとも感じています。

###疑問
dtoにセットするeggsはnullではなく、必ずListのインスタンスではいけないことを考えた時、
例1や例2以外の書き方は無いのでしょうか?
それとも自分の考え通りケースバイケースで使い分けるしかないのでしょうか?

どの言語でも共通の問題(というか感じること)だと思っているので、
みなさんの知恵をお貸しいただけたら幸いです。

よろしくお願いします。

4/12追記

みなさんのおかげで色んな考えに触れることができました。
ありがとうございます。今後はご回答にもあったように、
デザインパターンも活用していこうと思います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

iwamoto_takaaki

2016/04/08 15:40

例外の eggs = new ArrayList<String>();は例2じゃなくて例1に書くつもりだったんではないですか?例1と例2が等価ではないような気がします。
guest

回答6

0

どの言語でも共通の問題(というか感じること)だと思っているので、
みなさんの知恵をお貸しいただけたら幸いです。

他の言語ではよりスマートに書くための方法が用意されています。

###Null合体演算子とNull条件演算子を使う

たとえばC#では次のような書き方が可能です。

C#

1eggs = spam.getHam()?.getEggs() ?? new List<string>();

??をNull合体演算子と呼ばれ、前置がnullで無ければその値に、前置がnullの場合は後置の値になります。ショートサーキットであるため、前置がnullで無い限り後置は評価されないため効率的です。

?.はNull条件演算子と呼ばれ、前置がnullで通常のメソッドチェーンとしてメソッドが評価されますが、前置がnullの場合は続くメソッドは評価されずにnullが返ります。nullの場合でもNullReferenceException(JavaでいうNullPointerException)を発生させません。
これらの演算子は同じものまたはほぼ同じようなことができるものが他の言語でも用意されています。

  • PHPには??、Perlには//というNull合体演算子が存在します。
  • CoffeeScriptでは、Null合体演算子の代わりに存在演算子?(Null合体演算子との違いはnullだけでなくundefinedの場合も後置になる)があります。?.でNull条件演算子と同じような動作ができます。
  • Rubyでは、偽とされるのがnilとfalseのみという言語仕様であるため、||をNull合体演算子の代用として使用できます。また、&.(ぼっち演算子)はNull条件演算子と同様の動き(Rubyの場合はnullじゃなくてnilですが)をします。

###モナドを使う

たとえばScalaでは次のような書き方が可能です。

Scala

1eggs = Option(spam.getHam) 2 .flatMap {h => Option(h.getEggs)} 3 .getOrElse(Seq[String]())

Optionモナドを使ってnullを包み込み、NullPointerExceptionを発生させません。OptionモナドはHaskellでいうMaybeモナドのようなものであり、モナドが使用できるような関数型言語であればほとんどの場合で用意されています。

そして、Java8からはOptionalという似たようなことができるものが用意されました。

Java

1eggs = Optional.ofNullable(spam.getHam()) 2 .flatMap(h -> Optional.ofNullable(h.getEggs())) 3 .orElseGet(() -> new ArrayList<String>())

あ、結局Javaでも問題なかったですね。

投稿2016/04/08 23:05

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

外部から受け取る場合は別ですが、内部で完結している場合は、
spam.getHam()spam.getHam().getEggs()がnullを返さない形で実装すればnullチェックの必要はなくなるかと。

投稿2016/04/08 15:23

umed0025

総合スコア851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

質問の意図を取り違えているかもですが、
オブジェクトが実体化した時に、誰が責任を持つのか?という話になるのかな?
それとも、実体化して、初期値を取得する処理に、時間が係る場合と云う事なのかな?
ただ単に、コードの美しさの問題なのか?
例えば、
1.呼出側が責任を持つべき
2.呼ばれた側が責任を持つべき
3.どちらも、適切な処理をするべき
という単純化した話ではない?

投稿2016/04/09 05:41

daive

総合スコア2028

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

既に皆さんが十分な回答をされているので、ちょっと補足的な方法を。

swordone 様の回答で述べられている Dto クラスで処理を行う場合、static な生成補助メソッドと合わせて使うと、個別コンストラクタを用意する必要もなく対処ができるため幅広く効果的に使えるでしょう。
確か書籍 Effective Java なんかでも紹介されていましたよね。

Java

1public static Dto newInstance(List<String> eggs) { 2 Dto dto = new Dto(); 3 dto.setEggs(null == eggs ? new ArrayList<String>() : eggs); 4 return dto; 5} 6 7List<String> eggs = null; 8 9... 10 11Dto dto = Dto.newInstance(eggs);

呼出側で null を判定すること自体に必要性があれば元のコードにも意味があるわけですが、インスタンスの保証を必要とするのであれば、NullObject パターンを使うなり、返却時に値を保証するメソッドを別に用意する方が呼出側の負担を大きく軽減できる(何も考えずに利用できる)ため、結果的に楽で仕様に則した見やすいコードになるでしょう。null を返すことが重要で意味があるのかどうか?が一つの判断基準に使えると思います。

以上、ご参考になれば幸いです。

投稿2016/04/08 16:08

ps13zier

総合スコア433

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

投稿2016/04/08 15:15

tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

要はsetEggs()に渡す段階でeggsが確実にnull以外ならいいわけなので、
一旦nullで初期化しておき、tryでnull以外になれなかった場合に初期化すればいいのでは?

java

1Dto dto = new Dto(); 2List<String> eggs = null; 3 4try{ 5 Ham ham = hoge.fuga().getHam(); 6 if(ham != null){ 7 eggs = ham.getEggs(); 8 } 9}catch(Exception e){ 10 // 例外処理 11} 12 13if(eggs == null){ 14 eggs = new ArrayList<String>(); 15} 16 17dto.setEggs(eggs);

もしくは、Dtoクラスの方でsetEggsがnullを受け取った場合にArrayListを生成するという構造が自然かもしれません(渡す側でnullかどうか気を遣うよりは)。

投稿2016/04/08 15:15

編集2016/04/08 15:19
swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問