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

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

ただいまの
回答率

90.48%

  • Java

    14153questions

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

コンパイルエラーではなく、無限ループの理由

解決済

回答 6

投稿

  • 評価
  • クリップ 1
  • VIEW 1,784

k_mail

score 59

Java SE7 Silver の資格を目指し勉強中です。
分からない点は
・ 6,7行目でコンパイルエラーではなく、無限ループになる理由

1 public class Main{
2     public static void main(String[] args){
3        int[] array = {1,2,3};
4        for(int num : array){
5        int i = 1;
6        while(i <= num);
7          System.out.println(i++);
8        }
9     }
10}

答えは「無限ループになり、何も表示されない」です。
これは6行目がwhile(1 <= 1);となるからでしょうか

また、そうした場合、7行目に到達不可能なコードがあるように思い、コンパイルエラーになるのではとも思います。(選択肢には「コンパイルエラーが発生する」というものもあります)
なぜ、コンパイルエラーではなく、無限ループが答えになるのでしょうか

返信は夜になると思いますが、よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

+5

コンパイラの到達不能コード検出は通り一遍のものでして、
条件分岐(ifやwhileのことですね)の条件がどちらに転んだとしてもたどり着けない行があるときだけ検出してくれます。

もしもっと賢く、事実上到達できない行を検出するようにしようとしたらどうなるかというと、実際にコードを実行してみないといけなくなるため、このコードのように無限ループに陥るコードだとコンパイラがフリーズしてしまうことになります。だから、そんな“賢い”到達不能コード検出はされません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 04:13

    返信が遅くなり申し訳ございません。
    「 条件分岐(ifやwhileのことですね)の条件がどちらに転んだとしてもたどり着けない行があるときだけ検出」
    大変わかりやすく、勉強になりました。
    有難うございます。

    キャンセル

+4

これは引っかけ問題ですね。

ご質問のコードをEclipseなどのIDEに転記し、フォーマットを整形すると以下のようになります。

public class Main {
    public static void main(String[] args) {
        int[] array = { 1, 2, 3 };
        for (int num : array) {
            int i = 1;
            while (i <= num)
                ;
            System.out.println(i++);
        }
    }
}

じつは、

7          System.out.println(i++);

while句の外側に位置しており、while句の中でi++が実行されないため、正解は
「無限ループになり、何も表示されない」
となります。

---------以下、追記

失礼しました。

これは6行目がwhile(1 <= 1);となるからでしょうか

とおっしゃっているので、無限ループになることは認識されていたのですね。

なぜ、コンパイルエラーではなく、無限ループが答えになるのでしょうか

おそらく、【全ての】到達不可能コードをコンパイラに検出させることが難しいからではないでしょうか?
stackoverflowでも同様の話題があり、多分、そのような回答がなされていますw

http://stackoverflow.com/questions/3795585/why-does-java-have-an-unreachable-statement-compiler-error

ちなみに、以下のようにreturn句やthrow句のあとに実行行を書いた場合は、コンパイルエラーとなります。

return;
System.out.println("hoge");

これは、コンパイラから見ても到達不可能であることが明らかだからだと思われます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 04:12

    返信が遅くなり申し訳ございません。
    リンクも貼っていただき、勉強になります。
    有難うございました。

    キャンセル

checkベストアンサー

+3

コンパイラの立場になって考えて見れば、

public class Main {
 public static void main(String[] args) {
  while(true) ;  // 継続条件が確定でtrueで、breakがないから…
  System.out.println();  // どうやってもここ来れないじゃん -> エラー
 }
}
public class Main {
 public static void main(String[] args) {
  boolean b = true;
  while(b) ;  //boolean型の変数だけど、変化の余地があるな…
  System.out.println();  // 変更されたらここに来れるかもしれない
 }
}
public class Main {
 public static void main(String[] args) {
  final boolean b = true;
  while(b) ;  // boolean型の変数だけどfinal?じゃあtrueから動きようないな
  System.out.println();  // 絶対ここ来れないな -> エラー
 }
}
String str = "1";

if (1 == 2) {  // boolean型が返ってくるのはわかるけど、結果は今の時点じゃわからないな
    str = "2";  // 結果次第ではここ通るかもな
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 04:04

    非常に分かりやすかったです。
    有難うございます。

    キャンセル

+3

コンパイラはプログラムを実行しませんので、その時点の変数の値によって無限ループになる構文は、無限かどうか判断できません。
while(true);と書くと無限ループと判断してコンパイルエラーになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/23 16:20

    以下の環境ではコンパイルエラーとならず、実行もできました。

    マシン : MacBook Air 10.9.5
    JDK :
     1.6.0_65-b14-466.1
     1.7.0_45
     1.8.0_60

    実行コード

    public class Main {
     public static void main(String[] args) {
      while (true);
     }
    }

    コンパイラの実装によっても異なるのかもしれませんね。

    キャンセル

  • 2016/03/23 20:47

    Java コンパイラが無限ループに対してエラーを吐くことは無い…と思います。
    コンパイラがエラーと報告するのは、 while(true); のように明らかな無限ループの『後に』処理があるもの=到達不能コードで、無限ループそのものをエラー扱いはしないはずです。

    otn さんが言及しているのは、元の質問コードの 6 行目を書き換えると~という意味なのでしょう。

    キャンセル

  • 2016/03/23 21:41

    > 以下の環境ではコンパイルエラーとならず、実行もできました。

    到達不能文が何も書いて無いんですけど。それだとエラーになりようがない。無限ループ自体は正常です。

    キャンセル

  • 2016/03/23 21:57

    heignamerican 様、otn 様、ご指摘ありがとうございます。
    うっかりしておりました。

    おっしゃるとおり、以下のようにコードを修正すると、コンパイルエラーとなりました。

    public class Main {
     public static void main(String[] args) {
      while(true) ;
      System.out.println();
     }
    }


    ちなみに、以下のようにwhile句の中を変数化するとコンパイルできますが、

    public class Main {
     public static void main(String[] args) {
      boolean b = true;
      while(b) ;
      System.out.println();
     }
    }

    変数にfinal修飾子を付けると、再びコンパイルエラーとなりました。

    public class Main {
     public static void main(String[] args) {
      final boolean b = true;
      while(b) ;
      System.out.println();
     }
    }

    コンパイラの内部がうかがい知れるようで、興味深いですね。

    キャンセル

  • 2016/03/24 04:10

    返信が遅くなり申し訳ございません。
    実際にコードも書いて調べていただきありがとうございます。
    勉強になりました。

    キャンセル

+3

「プログラムが停止するかどうかを判定する」問題は停止問題という名前がつくぐらい由緒正しい問題ですが、「どんなプログラムについても、停止するかしないか正しく判定できる」方法は、存在しないことが示されています。

完璧を実現することは不可能な以上、コンパイラとしても「できる範囲だけすればいい」というわけで、コンパイル時に定数となる条件だけ判定する、というのが通常です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 04:06

    返信が遅くなり申し訳ございません。
    ご回答有難うございました

    キャンセル

+1

String str = "1";

if (1 == 2) {
    str = "2";  //実際は絶対入らないけどコンパイルは通る
}


みたいなコードでもコンパイルエラーにはなりませんね。
「判定した結果、到達しない」みたいなコードはコンパイルエラーにならない気がします。

判定などの要素が全く無く、かつ絶対にその先には行かない、という場合にエラーになる気がします。

String str = "1";

return;

str = "2";  //到達不可能 コンパイルエラー
String str = "1";

if (1 == 1) {
    return;
}

str = "2";  //これはエラーにならない
String str = "1";
int num = 0;

if (num == 0) {
    str = "a";
} else if (num != 0) {
    str = "b";
} else {
    str = "c";  //ここも絶対来ないけどエラーにならない
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/24 04:08

    返信が遅くなり申し訳ございません。
    「判定した結果、到達しないみたいなコードはコンパイルエラーにならない」
    勉強になりました。
    ご回答有難うございます。

    キャンセル

関連した質問

  • 受付中

    点数別分布グラフ

    点数分布のグラフですが、少し長いように感じました。もう少し短くすることはできますか? またこのコードに対して何かご意見がありましたらお願いします。 #inc

  • 解決済

    c# 入力について

    c#初心者です。 以下のような場合にどのようなコードを書けばよいのか分かりません。 ・2つの数値をスペース区切り(改行ではない)で入力し、結果として大きい方を出力するような場合

  • 解決済

    while文を利用して10000を4で割り続け、100より小さくなったらループを抜ける処理

    while文を利用して題名の処理を行いたいです。 以下のようにプログラムを書きましたが上手く行きませんでした。助言を頂けると幸いです。 int num = 10000;

  • 解決済

    1-100までの数値を生成し、1つのint型の配列にセットしたい。

    前提・実現したいこと 1-100までの数値を生成し、1つのint型の配列にセットして、 配列を呼び出してセットした値を表示したいです。 java初心者なので、かみ砕いて説明頂け

  • 解決済

    繰り返し処理について

    javaのプログラムの勉強をしているのですが、結果が112123になる意味が分かりません。最初のwhileでtrueを返して1が表示されて、インクリメントされてるんで、iは2になっ

  • 解決済

    不定のコマンドライン引数の整数を*に出力

     前提・実現したいこと ・コマンドライン引数から一つ以上の整数を受け取り、それぞれの引数に対応する数の*を出力する。 ・引数の値は不定 ・引数が与えられなかったときは「Usage 

  • 解決済

    標準入力から最小最大値を求める

    コンパイルがうまくいきません。 どこが間違っているか教えてください。 宜しくお願い致します。 【問題】 標準入力されている数字の最大と最小を求める 【標準入力されている数字

  • 解決済

    Javaのfor文とカウンタ変数について

     前提・実現したいこと 初めまして。 オラクルの資格本を参考にJavaの学習を行っております。 繰り返し文の章末問題の中で判らない箇所があったので、お教えいただきたく存じます。

同じタグがついた質問を見る

  • Java

    14153questions

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