- ベストアンサー
JavaにはなぜGO TO 命令がないのでしょうか?
皆さん教えて下さい。私はCOBOLを長年手がけ、最近Javaを勉強している者です。 JavaにはなぜGO TO 命令がないのでしょうか? IF ネストというのは、わかりにくく、私は昔から嫌っておりました。 ところがJavaにはGO TO 命令が無いため、いやでもIF ネストを使わねばならないようです。 それともわかりやすく効率的なコーディングが別にあるのでしょうか?? 3択の問題で、下記AはJavaの教科書的コーディングです。3択だからまだしも複雑になると、IFネストはわかりにくいと私は思います。 下記Bはわかりやすいですが、無駄な処理が発生し、良くないコーディング例です。 下記CはCOBOLコ-ディングで、GO TOが使えるため、人間が読んでわかりやすく、処理効率もいいです。 ●この点Javaをやっている皆さんどうお考えですか??? ------------------------------------------------------------------------------------ A<教科書的サンプル> if(a > 0){ System.out.println("aは正の値です。"); }else if(a == 0){ System.out.println("aはゼロです。"); }else{ System.out.println("aは負の値です。"); } ------------------------------------------------------------------------------------ B<if ネストを嫌った サンプル> if(a > 0){System.out.println("aは正の値です。");} if(a == 0){System.out.println("aはゼロです。");} if (a < 0){System.out.println("aは負の値です。");} 処理効率悪く、良くないプログラム例 ------------------------------------------------------------------------------------ C<COBOL なら> IF a > 0 DISPLAY "aは正の値です。" GO TO OWARI. IF a = 0 DISPLAY " aはゼロです。" GO TO OWARI. IF a < 0 DISPLAY " aは負の値です。" . OWARI. . GO TO 命令がある故に効率的 IF 構文の終わりと、OWARI の後ろにピリオドがあります。 ------------------------------------------------------------------------------------
- みんなの回答 (19)
- 専門家の回答
質問者が選んだベストアンサー
goto は自由すぎるので, 「うまく使えば」強力なんだけどうまく使えないとプログラムがとてつもなく読みにくくなってしまいます. ということで, 今どきの言語では「管理した goto」を導入し, 自由すぎる goto の使用頻度を極力減らす (あるいは goto そのものをなくしてしまう) のが普通です. その「管理した goto」が break や continue などです. あと, 確かに if~else if~ というのは構文的に「if のネスト」なんだけど, 多くの場合そのようには意識しません. この全体を見て「多方向分岐という構造である」と認識します. 逆に C や Java に慣れた目から見ると, その COBOL の書き方の方が「読みにくい」と映ることでしょう. つまり, C や Java のプログラマにとって「else if」は見慣れた構造なので特に悩むことなく一目で「多方向分岐」と判断します. ところが COBOL の書き方では先頭のキーワードがすべて「IF」なので, すべての場合が背反であるかどうかを判定するためには文の最後まで見なければなりません. そこにコストがかかるということも念頭に置かねばなりません. いずれにしても「読んでわかりやすい」かどうかは「読む人がその言語にどのくらい慣れているのか」ということを抜きにして考えても無意味です. 以下余談: C に goto は存在しますよ>#1. C++ にだってある. Java の場合 goto は予約語ではあるけど機能を持っていないんだっけな? 余談その2: 「else if」構造に対する特殊な構文を持っている言語も存在します. 余談その3: 「goto の自由度」という意味では Pascal が最強に近いかなぁ.
その他の回答 (18)
補足:昔流行った構造化プログラミングというのは、本来は「もっとプログラムの構造を明確にして、分かりやすくメンテナンスしやすいプログラムを書こう」という趣旨で、その議論の中でgotoがあまりにも自由すぎて構造が分かりにくいプログラムができやすい、という話が出てきたと思います。あくまでも、出来やすい、ということです。 それがいつの間にか、「とにかくgotoは諸悪の根源」というパターン的な思考になってしまったきらいがあると思います。(ジョーク論文で「gotoをやめてcome from 文を導入しよう、などというものもありました。あくまでジョークで、意味はありません。) 結局、大事なのは、質問者様のようにきちんとプログラムを書く、という姿勢の方であって、gotoがあろうがなかろうが、CobolでもJavaでも分かりにくいプログラムはいくらでもできる、と思います。 取り合えず、elseは一種の制限付きgotoと思うしかないと思います。 >人間の頭は仕様記述の際に、女は男のelseだとは考えません。 それは確かに。(No.8さんの意見に似てますが。) if( sex == male ){ 男に関する処理 } else { 女に関する処理 } では「女は男のelse」になってしまいますが、 if( sex == male ){ 男に関する処理 } else if( sex == female ){ 女に関する処理 } else { sexの値が異常であった場合の処理 } という形なら、女は男のelseということにはならない、という考え方もあります。 elseがどうしてもいやなら、No.14さんに似た形ですが、 abc: { if(...) { .... break abc; } if(...) { ... break abc; } } という書き方もあるかもしれません(こういう使い方でbreakを使ったことがないので、うまくいくかどうか分からないのですが・・・文法上は大丈夫なのかな?今、確かめる時間がないものですみません)。 (ええと、No.1さん。C言語にはgoto文はありますよ(^^;))
下の回答者様でも何回か指摘されていますが、やはり、goto文があまりにも自由すぎる、ということだと私も思います。 文章を読むと、質問者様はしっかりしてらっしゃるのでgotoを使っても大丈夫だと思いますが、大丈夫でないプログラマも沢山いるわけです。 質問者様の例では、慣れの問題が大きいと思いますが、cobolの例を少し変えて、各gotoの行き先が全部バラバラだったら途端に分かりにくくなります。 そういう分かりにくいgotoを使わない、と自主規制を堅持するなら良いですけど、堅持しない人もいるわけで。 結局、gotoを使うときのよくあるパターンを制御構造にして「わざと自由を制限した」のだと思います。 C言語では、2重以上の繰り返しループから一気に抜け出す、などの場合には、やはりgotoがあった方が自然に書けるのでgoto文はありましたが、Javaではbreak文の機能が強化されたために、そういうgotoも必要なくなった、ということでJavaではgotoがなくとも十分プログラム可能だということで採用されなかったのではないかと思います。 ちなみに、C言語ではmallocなどで領域確保したらプログラマがfreeするわけですが、Javaでは領域開放などという危ない操作は言語処理系に任せてプログラマは手をつけるな、という感じで明示的な領域開放手段もありません。これも、自由を制限することで安全性をとったと思われます。
- choconamacream
- ベストアンサー率44% (152/338)
/** elseと書いて、「えるす」と読む。 日本語訳は、「~でなければ」(接続詞)ですね。 けっこう多用してると、若手のJavaプログラマと 仲良くなれたりとか~。 逆にハマっちゃって、「gotoよ、いずこ?」 ってなっちゃうかもね。 */ enum SEX {MALE, FEMALE} // JDK5 public class GOTO{ public static void main(String... args){ _goto(SEX.MALE,40); _goto(SEX.MALE,39); _goto(SEX.FEMALE,41); _goto(SEX.FEMALE,38); } public static void _goto(SEX s,int AGE){ String HOKYU = ""; switch(s){ case MALE: if(AGE >= 40) {HOKYU="1"; break;} ; if(AGE < 40) HOKYU="2"; break; case FEMALE: if(AGE >= 40) {HOKYU="3"; break;} ; if(AGE < 40) HOKYU="4"; break; } System.out.print(s.toString() + " " + String.valueOf(AGE)); System.out.println("歳 → " + HOKYU + "号棒"); } }
- Tacosan
- ベストアンサー率23% (3656/15482)
何回も書かれているんだけど, goto が嫌われている (あるいは gtoto が捨てられてしまっている) 理由は「goto があまりにも自由すぎるから」です. #11 でも指摘してるんだけど, else if コンストラクトにおける else は事実上 goto と同じ意味を持ちます. つまり, この構造において else は「制限された goto」として働きます. で, 実際 COBOL で書いた場合でもこの「制限された goto」で十分でしょ? ついでにいえば, この形で書くごとに段落が増えていくのもどうかと思うな~.
- atse
- ベストアンサー率83% (36/43)
私はCOBOLはおろかJavaも全然わからないのですが、 郷に入れば郷に従えといいますし、下記のように関数化することで、 if 続きでも無駄を増やさず同じような工程を辿れると思います。 public static int HOKYU; public static void main(String[] args) { hCheck("FEMALE", 51); System.out.println("HOKYU=" + HOKYU); } public static void hCheck(String SEX, int AGE){ //IF (SEX = MALE) AND (AGE GREATER OR EQUAL 40) MOVE 1 TO HOKYU //GOTO OWARI. if(SEX.equals("MALE") && AGE >= 40) { HOKYU = 1; return;} //IF (SEX = MALE) AND (AGE LESS 40) MOVE 2 TO HOKYU //GOTO OWARI. if(SEX.equals("MALE") && AGE < 40) { HOKYU = 2; return;} //IF (SEX = FEMALE) AND (AGE GREATER OR EQUAL 40) MOVE 3 TO HOKYU //GOTO OWARI. if(SEX.equals("FEMALE") && AGE >= 40) { HOKYU = 3; return;} //IF (SEX = FEMALE) AND (AGE LESS 40) MOVE 4 TO HOKYU //GOTO OWARI. if(SEX.equals("FEMALE") && AGE < 40) { HOKYU = 4; return;} //ERROR-SHORI. System.out.println("ERROR-SHORI"); }
お礼
buriです、ちょっと留守にしておりました。returnを使うのはグッドアイデアですね。これは思いつきませんでした。14番の方のbreakを使うのがCOBOL頭には一番なじみやすいです。皆さんの回答を頂いて、まあ着地点は 1)breakか、 2)elseif(敢えて他の何だったかの言語のように、elseとifがくっついていると思ってしまう)を、嵌め込んでelseifでないときは{ }の処理をした後、すぐ下へgotoが潜在していると思う、・・・・・のが答えかなと思いました。
- moritan2
- ベストアンサー率25% (168/670)
} else if(...) { はCとかjavaで複数の条件を処理するための普通の構文なので、非常に分かりやすいと思います。これを嫌う理由は無いと思います。 トリッキーな書き方はありますが、、、 do { if(...) { .... break; } if(...) { ... break; } } while(false); 基本的にはお勧めしません。 どうしても嫌いな物はしかたがありませんが、その場合は java を使う事を諦めるしかないでしょう。
- BetaNona
- ベストアンサー率50% (1/2)
はっきり言ってまったくお勧めしたくありませんが、どうしてもelseが嫌だ!ということであれば、breakをgoto代わりに使うという手はあります。 do{ if(a > 0){ System.out.println("aは正の値です。"); break; } if(a == 0){ System.out.println("aはゼロです。"); break; } if (a < 0){ System.out.println("aは負の値です。"); break; } }while(true); //breakでここに飛んで来る while(true)は今時のまともなコンパイラならまず実際の処理はしませんので、効率は問題ありません。
- Tacosan
- ベストアンサー率23% (3656/15482)
あ, #7 の「お礼」のところのプログラムを見てもう 1つ気になったのですが, IF (SEX = MALE) AND (AGE LESS 40) MOVE 4 TO HOKYU . (← ピリオドあり) ERROR-SHORI. はおかしいですね. 見事にバグってます (というか, そもそも「ピリオドだけ」って書けたんだっけ).
お礼
buriです。仰るとおりミス。コピーして貼り付ける時急いで間違えました。IF (SEX = FEMALE) AND (AGE LESS 40) MOVE 4 TO HOKYUです。 COBOLでは、画面上何行書こうが、ピリオドまでが1つの文です。 ピリオドの位置は72桁より以前に書く(カード時代の名残)、最近のCOBOLはそうでないならご容赦。
- Tacosan
- ベストアンサー率23% (3656/15482)
#7 の「お礼」のところの仕様を見てふと気になったのですが, この仕様に厳密に忠実にコーディングするなら GO TO の入る余地はないような気がします. 仕様には「そこに GO TO を入れる」とは書いてありませんね. ということは, この仕様を読んだときに「何らかの理由」で自動的に「全ての条件が互いに排反である」ということを読み取ったわけですよね. ならば, 「GO TO を入れる」ことと「else を入れる」こととは同じはずです.
- foxa-gogo
- ベストアンサー率44% (38/85)
>即ち、人間の頭は仕様記述の際に、女は男のelseだとは考えません。 どんな官庁や民間の規則でも、上記仕様書のように書かれているはずです。 >COBOLはそれをそのままコーディングできる訳です。 >その際にIFと GO TOが必須となると思います。 昔のCOBOLの時代にも、IF ELSEのネストでコーディングする人は少数いました。しかしこんなプログラムは仕様変更や追加を他人がやる場合には困ったものでした。 なるほど、興味深いご意見ですね。 Javaプログラマに人気の書籍、Code Completeによれば、こういう場合は、テーブルを使用したルックアップが有効と書いてありました。
- 1
- 2
お礼
buriです、本当はもっと前に書きたかったですが、この回答欄は1000文字までなので書けなかったことです。goto文を排斥する構造化論者は昔から居ました。でも私は次のようにしていました。 COBOLであっても、なるべく、1つのプログラム(大体2000から3000ステップ以下)の中でも、概ね60行くらい(なぜ60かというとラインプリンタ1頁分が60行位だから=即ち1目で見える範囲)に収まるようなるべくモジュール化を考える。 goto文での飛び先はなるべくそのモジュールの中に留める。 いくら何でも2000行の中であちこちgotoで飛んだらそれはスパゲッティプログラムそのもの、話になりません。 goto文を排斥するのは、包丁が人殺しに使われるから禁止するのと同じと思いますよ。 昔の構造化論者も実務を知らない学者が多かったと思います。 さてこの目でJavaの構文を見るとgotoを排斥したが故に無理をしてるなーと思います。 どこが?ともし御質問あれば、次回に。何しろ1000文字の制限はきつい。