ネストしたメソッドでの変数のスコープについて

このQ&Aのポイント
  • ネストしたメソッドにおける変数のスコープについて調べましたが、返り値が反映されない問題があります。
  • 変数に代入するとうまく動作するようですが、原因はスコープにありますか?
  • コメントアウトしているif文の中をi = nest(i); にすると、想定通りの結果が得られます。
回答を見る
  • ベストアンサー

ネストしたメソッドにおける変数のスコープ

mainからnestというメソッドを呼び出し数を数えて出力するという単純なプログラムなのですが、返り値が反映されません。変数に代入すると、うまくいくのですが、スコープが原因なのでしょうか?検索しても仕組みが分かりませんでした。 System.out.println("nest: " + nest(0)); static int nest(int i){ i++; System.out.println("i: " + i); if(i<5) { nest(i); } // i = nest(i); // works ? return i; } 出力: i: 1 i: 2 i: 3 i: 4 i: 5 nest: 1 コメントアウトしているif文の中をi = nest(i); にすると、nest:5になります。

  • Java
  • 回答数3
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • utun01
  • ベストアンサー率40% (110/270)
回答No.2

そもそも戻り値を使っていないからでしょう。 if(i<5) { nest(i); } では、nest()を呼び出しても、戻り値を何処にも入れていません。 再帰処理では、再帰される毎に別のメモリ空間が使われますので、アドレス参照しているもの以外は引き継がれません。

wanwalker
質問者

補足

javaで再帰される毎に別のメモリ空間が使われていたことは知りませんでした。スクリプト言語では気にしていなかったのですが、C言語に近い挙動なんですね!

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

#2 では「再帰」って言ってるけど, 実際には再帰に限らずメソッドを呼び出すごとに別のメモリ領域を使います. たとえば (適当なクラスの中で) static void main(String [] args) { foo(3); } static void foo(int n) { int i; for (i = 0; i < n; ++i) { bar(i); } } static void bar(int n) { int i = 2*n+5; System.out.println("i = " + i); } としたらどのような動作をして何が出力されるかわかりますか?

wanwalker
質問者

補足

javaで再帰されるごとに同名の別のメソッドを呼び出していたのは知りませんでした。メソッド内で定義された変数のスコープはメソッド内に限られることは知っていたのですが、再帰すると、恐らくスタックメモリのような別のメモリ空間を使用していたのは知りませんでした。javaはまだ始めたばかりなので、もう少し頑張ろうと思います。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

何を期待してる?

wanwalker
質問者

補足

nest:5 iを1つずつ加え、i:5も出力もしているのに、mainに戻すと1が出力されます。iに毎回代入していくと、5が戻るのですが、どうしてでしょうか?まるで、iが2つあるかのようです。

関連するQ&A

  • 静的変数と静的メソッドの使い方について

    独習JAVAにてJAVAを学習しています。「コマンドライン引数を受け取り、それをスペイン語表記に変換して表示するアプリケーションを作成しなさい。例えば、OneはUno、・・・、FiveはCincoになります。静的メソッドを使って実現しなさい」という問題で躓きました。以下、私が作成したプログラムです。 class Language { static String st[] = new String[5]; //静的初期化ブロックは実行しない。 //コマンドライン引数を受け取るmainメソッドが使えないため //静的メソッド static String translation(){ for(int i = 0; i < st.length; i++) { if(st[i] == "One") return st[i] = "Uno"; if(st[i] == "Two") return st[i] = "Dos"; if(st[i] == "Three") return st[i] = "Tres"; if(st[i] == "Four") return st[i] = "Quatro"; if(st[i] == "Five") return st[i] = "Cinco"; } } //21行目 } class StaticalMethodPractice { public static void main(String args[]) { //mainメソッドが登場したので、静的変数を初期化する for(int i = 0; i < Language.st.length; i++) Language.st[i] = args[i]; //静的メソッドを実行 System.out.println(Language.translation()); } } このプログラムに対して、21行目return文が指定されていませんというエラーメッセージが出てくるのですが、そもそもreturnの使い方もよく分からないので右往左往している状況です。低級な質問かもしれませんが、よかったらアドバイスの方よろしくお願いします。

  • プログラムの合体。

    jump7799_4836さん 2018/7/2103:34:44 public class Test2 { public static int メソッド () { System.out.println("メソッド()が呼ばれました"); return 0; } public static int メソッド (int i) { System.out.println("メソッド(int i)が呼ばれました"); return i; } public static int メソッド (int i, int j) { System.out.println("メソッド(int i, int j)が呼ばれました"); return i; } public static int メソッド (short s) { System.out.println("メソッド(short s)が呼ばれました"); return s; } public static int メソッド (double d) { System.out.println("メソッド(double d)が呼ばれました"); return (int) d; } } public メソッド class Test2 { public メソッド static void main(String[] args) { Test2.メソッド (); Test2.メソッド (1); Test2.メソッド (1,2); Test2.メソッド (1.1); Test2.メソッド ((short) 1); Test2.メソッド ((double)1); } } kouzou@GD348ZZD9:/WORK$ javac Test2.java Test2.java:29: エラー: class、interfaceまたはenumがありません public メソッド class Test2 { ^ Test2.java:30: エラー: <identifier>がありません public メソッド static void main(String[] args) { ^ エラー2個 2つのプログラムが合体することってあるのですか? いつもすみません。 解説のほど、宜しくお願い申し上げます。

    • ベストアンサー
    • Java
  • クラス変数/メソッドとインスタンス変数/メソッドの見え方について

    Javaの言語仕様(?)についてお教え下さい。 参照変数の型がインスタンスのスーパークラスの型の時、クラス変数/メソッドとインスタンス変数/メソッドの見え方が納得いかずに困っています。 以下のような条件の時です。   ・クラスが2つあり、1つはもう1つのクラスを継承しています。     それぞれを「スーパー」「サブ」と以下で呼びます。   ・インスタンスは"サブ"の型です。   ・上記インスタンスへの参照変数は"スーパー"のクラスの型です。   ・"スーパー"、"サブ"ともに【同名】の「クラス」変数/メソッド、「インスタンス」変数/メソッドがあります。 この場合に、"サブ"のインスタンスを参照している"スーパー"の型の変数を介し、それらにアクセスしたらどれが見えるか?という疑問です。 実験結果では以下のようになりました。           [フィールド]  [メソッド]   [1.static ]  スーパーの   スーパーの   [2.非static]  スーパーの   サブの 納得いかないのは「2.非static」で「フィールド」が、「スーパーの」になるところです。 これも「サブの」になると思っていました。 なぜサブクラスのが見えないのでしょうか? 同名の変数なのでスーパークラスのはサブクラスので隠れされ、サブクラスのが見えると思っていたのですが。 参考書には以下のように書いてありました。   フィールドの場合、参照変数の型のものが見える。   メソッドの場合、インスタンスの型のものが見える。 私には不自然に感じられるのですが、「こういう仕様だから。」と納得するしか無いのでしょうか? 「なぜこうなるか」について説明がある文献、サイトなどありましたらお教えください。 参考までに以下が実験したサンプルコードと結果です。長くて申し訳ありません。 「サンプルコード」 public class Super { static int staticField = 10; int instanceField = 100; static void staticMethod() { System.out.println( "staticField = " + staticField ); } void instanceMethod() { System.out.println( "instanceField = " + instanceField ); } } public class Sub extends Super { static int staticField = 90; int instanceField = 900; static void staticMethod() { System.out.println( "staticField = " + staticField ); } void instanceMethod() { System.out.println( "instanceField = " + instanceField ); } } public class TestStatic { public static void main(String[] args) { // インスタンスはSub、参照変数もSub、という状態。 Sub sub = new Sub(); System.out.println( "実験1" ); System.out.println( "1.クラス変数      " + sub.staticField ); System.out.print( "2.クラスメソッド    " ); sub.staticMethod(); System.out.println( "3.インスタンス変数   " + sub.instanceField ); System.out.print( "4.インスタンスメソッド " ); sub.instanceMethod(); // インスタンスはSub、参照変数はSuper、という状態。 Super sup = new Sub(); System.out.println( "実験2" ); System.out.println( "5.クラス変数      " + sup.staticField ); System.out.print( "6.クラスメソッド    " ); sup.staticMethod(); System.out.println( "7.インスタンス変数   " + sup.instanceField ); System.out.print( "8.インスタンスメソッド " ); sup.instanceMethod(); } } 「結果」 実験1 1.クラス変数      90 2.クラスメソッド    staticField = 90 3.インスタンス変数   900 4.インスタンスメソッド instanceField = 900 実験2 5.クラス変数      10 6.クラスメソッド    staticField = 10 7.インスタンス変数   100 8.インスタンスメソッド instanceField = 900 納得が行かないのは7のところです。 以上よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 再帰メソッドについて

    いつもお世話になっております。 再帰メソッドについて質問があります。 後述のプログラム実行後、以下の結果が 得られました。 ********** depth = [0] , value = [0] ********** depth = [1] , value = [1] ********** depth = [2] , value = [2] ########## depth = [2] , value = [3] …★ ########## depth = [1] , value = [3] recursionMethod() は3回呼ばれました。 (以下、ソース) public class RecursionTest { private static final int MAX_DEPTH = 2; private static int cnt = 0; private int val =0; public static void main(String[] args) { // 再帰メソッドの呼び出し RecursionTest own = new RecursionTest(); own.recursionMethod(0); System.out.println("\n recursionMethod() は" + cnt + "回呼ばれました。"); } private void recursionMethod(int depth) { // 再帰メソッドが呼ばれた回数をカウントする cnt++; System.out.println("********** depth = [" + depth + "] , value = [" + val + "]"); val++; // パラメータ depth が MAX値に到達したら、return する if (depth++ >= MAX_DEPTH) { return; } // 自分自身の呼び出し recursionMethod(depth); System.out.println("########## depth = [" + depth + "] , value = [" + val + "]"); } } 実行結果の★以降が得られる理由が全く分かりません。 ・return で main() に戻るはずなのになぜ「###~」のログが出力されるのか ・depth の値がなぜデクリメントされるのか (誰がデクリメントの処理をしているのか) そもそも上記の結果を返すことが「メソッドの再帰的呼び出し」ということなのでしょうか? ご教授頂ける方がいらっしゃいましたら、宜しくお願い致します。

    • ベストアンサー
    • Java
  • getter、setterメソッドを活用したいです

    Javaのgetter、setterメソッドをうまく使って、下記のコードを実行しようとしたのですが。 ---------------- package javatest; public class Jidosha { private int num; private double gas; public void setNum(int num) { this.num = num; } public void setGas(double gas) { this.gas = gas; } public int getNum() { return num; } public double getGas() { return gas; } public static void main(String args[]) { System.out.println("この車のナンバーは" + num + "です。"); System.out.println("この車のガソリンが入る最大量は " + gas + "です。"); } } ---------------- Eclipse上では「System.out.println・・・」のところで「非 static フィールド gas を static 参照できません」といったエラーが出てきまして。 getter、setterメソッドをうまく活用して「この車のナンバーは××××です」「この車のガソリンが入る最大量は〇〇〇〇です。」という文を出力するには、どう書けばよいでしょうか。 よろしくお願い致します。 ※OKWAVEより補足:「Webシステム開発」についての質問です。

    • ベストアンサー
    • Java
  • 教えて下さい!

    以下のプログラムがわかりません。 最近学び始めたのですが、うまく理解できない所があります public static void main(string[]args) int i=99 system.out.printIn(f(i)); static int f(int i) if(i<=0) return 0; else if(i%2==0) return 1+f(i -1) else return f(i-1); 少し省いてますが、このプログラムを実行した時の出力される整数、 メソッドfは何を計算しているのか? いろいろと調べてみてもわからないので、どなたかご教授お願いします!

  • java ネストしたfor文について

    ***** **** *** ** * 上のように*が減るようにしたいのですが下のソースではどこが悪いか教えてください class TestGoo{ public static void main(String args[]){ for(int i = 5; i>=1; i--){ for(int j = 5;j>=1; j--){ System.out.print('*'); } System.out.println(); } } }

  • 昇進者です。 戻り値の学習をしていますが。

    *を10個表示するプログラムですが。 public class Graph1 { public static void main(String[] args) { printGraph(10); } public static void PrintGraph(int x) for(int i = 0; i < x; i++){ System.out.println("*"); } System.out.println(""); } } のprintGraph(10);は何のためにあるのですか? 10がxに代入されていますよね。戻り値はxですか。

  • アルゴリズム

    public class A1 { public static void main(String[] args) { int[] dataes = {10, 8, 9, 3, 2, 1, 4, 6, 5, 0}; System.out.println("result index = " + search(dataes, 2)); } public static int search(int[] dataes, int valueToFind) { for (int i = 0; i < dataes.length; i++) { if (dataes[i] == valueToFind) { return i; } } return -1; } } このプログラムのフローチャートを教えてください

    • ベストアンサー
    • Java
  • mainクラス内に書いたメソッドの宣言の仕方(staticの必要性)

    java を勉強中の超初心者です、宜しくお願いします。 main と同じクラスに disp というメソッドを作成してやり、” void disp(int a , int b )”と書いてやりましたが、mainからアクセス出来ません。 そこで、” static void disp(int a , int b )” という風に” static ” を先頭につけてやりましたら、うまく動きました。 これは、mainメソッドから他のメソッドにアクセスする場合には、必ず” static ” をつけてやる必要があるということでしょうか。 ======================================================= class クラス練習 { public static void main(String[] args) { disp(5,10); } /*static*/ void disp(int a , int b ) { System.out.println("a+b = " + (a+b)); } }

    • ベストアンサー
    • Java

専門家に質問してみよう