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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

2383閲覧

Java:変数が初期化されていない

akamarukun

総合スコア27

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/05/29 01:50

Java

1public static void main(String[] args) { 2 // TODO 自動生成されたメソッド・スタブ 3 4 int time = new java.util.Scanner(System.in).nextInt(); 5 String greeting; 6 String message = ("ただ今の時刻は" + time + "時です"); 7 8 if (time >= 4 && time <=10) { 9 greeting = "おはようございます"; 10 } else if (time >= 11 && time <= 17) { 11 greeting = "こんにちは"; 12 } else if (time == 18) { 13 greeting = "こんばんは"; 14 } else if ((time >= 19 && time <= 23) || (time >= 0 && time <= 3)) { 15 greeting = "おやすみなさい"; 16 } 17 18 System.out.println(greeting); 19 System.out.println(message); 20 21 }

以上のコードで実行すると、greetingが初期化されていない旨のコンパイルエラーがでます。
自分的には、しているつもりなんですが、どこがおかしいんでしょうか?
初心者なので、よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

どの条件も成立しなかった場合は未設定の状態になり得ます。例えば間違って25と入れたら・・・

Javaでは変数の値は「必ず設定されていることがコンパイラーが納得しない限りは参照できません」コンパイラーを納得させるためには以下のようにしましょう。

java

1String greeting; 2 3if (...) { 4 greeting = ...; 5} else if (...) { 6 greeting = ...; 7} else if (...) { 8 ... 9} else { 10 greeting = ...; // どの条件にも合致しなくても必ず値が設定されるようにしておく 11 // or 12 return ...; // これ以降の実行を止めることを明示する 13 // or 14 throw ...; // これ以降の実行を止めることを明示する 15} 16System.out.println(greeting); // 必ず設定されている保証の元で参照する

追記:本件に直接関係ないですが、mts10806さんがコメントくださった点について少し追記してみます。以前似たようなQ&Aがあったかと思いますが、自分は「変数のとりあえずの初期化」は避けます。理由はなるべく変数をfinalとして扱いたい(つまり途中で値が変わる変数にはしたくない)からです。

途中で値が変化する変数ももちろん使いますが使わずに済ませられることも多いです。Javaの仕様はいくぶん厳格でfinalでない変数は内側のスコープからアクセスさせてやんないという仕様なのでそういう点からもなるべくfinalにしておこうと考えます。(本末転倒な論理ですね。本来は極力finalにしようってのが本質だと思います。)

java

1String greeting; // (A) 2if (...) { 3 greeting = ...; 4} else if (...) { 5 greeting = ...; 6} else { 7 greeting = ...; 8} 9Button button = new Button("Hi"); 10button.setOnAction(ev -> System.out.println(greeting)); // <= (B)

例えば上のコードだとgreetingはfinalと見做してくれるためラムダ式の本体(B)で参照できます。これを(A)で「とりあえず初期化」としてしまうとfinalではなくなるため(B)で参照できなくなるという「面白くないこと」になります。

この辺り言語によって違うようですが、JavaScript, Python, Scala, C#などだとfinalじゃなきゃ内側のスコープで参照できないという制約はありません。どうも大半のモダンな言語はそういう制約は課してないようです。しかしこれがJavaだと「副作用を持たない行儀良いコードだけ外側のスコープの変数をアクセスさせてやる」といった気難しいオジイチャンのような仕様です。

「finalでないものがアクセスできないなんて言語機能が足りてないんじゃないの?」と思ったこともありますが、「まぁまぁそういわずfinalにすることを意識する方がいいと捉えよう」と前向きに考えるようにしました。

(finalじゃない変数しか内側からアクセスできないってのはJavaぐらいかも知れません。実際は行儀良いコードにだけ内側からのアクセスを許すという意図があるのか、単に実装がめんどかったのでまぁできなくていいよねぐらいのノリなのか本当のところは自分には分かりません。ただ変更可能なローカル変数を内側のスコープからアクセスできるようにするとそれなりの性能的代償があるとは思います。ScalaやC#はその代償をプログラマーが意識していない実装の中でこっそり支払っています。そうした細かい点を気にせず制限なく使える言語がいいのか、制約がある理由を把握した上で使う方がよいのか・・・自分には何とも言えません。)

投稿2018/05/29 01:58

編集2018/05/29 06:23
KSwordOfHaste

総合スコア18394

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

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

akamarukun

2018/05/29 02:06

解決いたしました。ご丁寧にありがとうございます。
m.ts10806

2018/05/29 02:15

個人的に回答者さんにお聞きしたいのですが、 elseを用意して必ずどこか通るようにするのと、先に初期値を入れておくのと どちらがベターでしょうか? 要件次第とはなると思うのですけど。 そういえば、初期値を入れた上でもelseを設置するケースもありますね。
m.ts10806

2018/05/29 06:48

追記ありがとうございます。大変参考になりました。
guest

0

ベストアンサー

そのif文全部に合致しない場合、初期化されませんね。
そのため、そのエラー(ワーニング?)がでています

投稿2018/05/29 01:53

y_waiwai

総合スコア87774

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

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

akamarukun

2018/05/29 02:05

意味が分かりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問