メソッド

<本章の目的>メソッドを習得する。変数の有効範囲についても考察します。やっとメソッド解禁だー(笑)!

問題8-1 半額の計算をするメソッドを定義して下さい。

○答え

public class Discount2{
  public static void main(String[] args){
    int p,q;
    p=1000;
    q=halve(p);
    System.out.println("元の値段が"+p+"円なら、半額だと"+q+"円になります。");
  }
  public static int halve(int n){
    return n/2;
  }
}


○実行結果

D:\atsushi\Java\List8-2>java Discount2
元の値段が1000円なら、半額だと500円になります。
-- Press any key to exit (Input "c" to continue) --

○解説

public はクラスのアクセス制御キーワードです。
C++言語みたいに、まとめて書くわけにはいかないみたいですね。
省略してもエラーは出ないけれど、やっぱり private って見なされてるのかな?
クラス内部からじゃ確かめようがないけれど(汗)。

static はクラスメソッドであることを示している……らしい。
詳しくはクラスの解説の時に。

メソッドの名前には、英語の大文字( A 〜 Z )、小文字( a 〜 z )、下線文字( _ )、数字( 0 〜 9 )、
それから Unicode に登場する数多くの文字が使えます。
ただし、数字から始まる名前は使えません。

ところで、C言語では関数を呼び出す前に宣言する必要がありました。
答えでは、宣言する前に呼び出しちゃってますよね。
これって大丈夫なの?と思われたかも知れません。
私も一瞬そう思いました。
しかし、C++言語のクラスではメンバー関数の並び順に意味はありません。
Java言語のクラスもC++言語のクラスと同じだと考えれば、
ちょっと違和感は残りますが、納得できるのではないかと思います。

問題8-2 引数で指定した個数だけ「*」を表示して改行するメソッドを定義して下さい。

○答え

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.print("*");
    }
    System.out.println("");
  }
}


○実行結果

D:\atsushi\Java\List8-3>java Graph1
**********
-- Press any key to exit (Input "c" to continue) --

○解説

戻り値のないメソッドは return 文を省略することが出来ます。
省略せずに return; とだけ書くことも出来ます。

main メソッドは return 文を省略していますね。

問題8-3 引数の累乗を計算するメソッドを定義して下さい。

○答え

public class Power1{
  public static void main(String[] args){
    System.out.println(getPower(2,3));
  }
  public static int getPower(int x,int n){
    int y=1;
    for(int i=0;i<n;i++){
      y*=x;
    }
    return y;
  }
}


○実行結果

D:\atsushi\Java\List8-4>java Power1
8
-- Press any key to exit (Input "c" to continue) --

○解説

引数の個数は幾つでも( 0 個でも)問題ありません。

問題8-4 引数で指定した文字を引数で指定した個数だけ表示して
        改行するメソッドを定義して下さい。
        文字の指定は省略できるものとし、省略した場合は「*」を表示することにします。


○答え

public class Graph2{
  public static void main(String[] args){
    printGraph(10);
    printGraph(5,'+');
  }
  public static void printGraph(int x){
    for(int i=0;i<x;i++){
      System.out.print("*");
    }
    System.out.println("");
  }
  public static void printGraph(int x,char c){
    for(int i=0;i<x;i++){
      System.out.print(c);
    }
    System.out.println("");
  }
}


○実行結果

D:\atsushi\Java\p198>java Graph2
**********
+++++
-- Press any key to exit (Input "c" to continue) --

○解説

メソッドを多重定義しています。

○補足

ディフォルト引数を指定したらどうなるでしょうか?

public static void printGraph(int x,char c='#'){

//コンパイル

■D:\atsushi\Java\p198> javac Graph2.java
Graph2.java:12: ')' がありません。
public static void printGraph(int x,char c='#'){
                          ^
Graph2.java:18: ';' がありません。
}
^
エラー 2 個

どうやらディフォルト引数は使えないみたいですね。

問題8-5 変数の有効範囲を確かめて下さい。

○答え&解説

//例 1

public class NameSpace{
  public static void main(String[] args){
    int i;
    for(int i=0;i<3;i++){
      System.out.println(i);
    }
  }
}


//コンパイル

■D:\atsushi\Java\p192> javac NameSpace.java
NameSpace.java:4: i は main(java.lang.String[]) で定義されています。
for(int i=0;i<3;i++){
    ^
エラー 1 個

//解説

for 文の引数で宣言された変数は for ループ内部でしか使うことが出来ません。
つまり、ブロック内部で宣言されているも同然です。
それならば、答えのような変数宣言も許されるような気がしますが、
コンパイラが教えているようにエラーです。

//例 2

public class NameSpace{
  public static void main(String[] args){
    for(int i=0;i<3;i++){
      System.out.println(i);
    }
    int i=10;
    System.out.println(i);
  }
}


//実行結果

D:\atsushi\Java\p192>java NameSpace
0
1
2
10
-- Press any key to exit (Input "c" to continue) --

//解説

例 1 と変数宣言する順番が逆転している場合です。
C言語、C++言語プログラマの私には、むしろこれがエラーにならない方が不思議ですが、
for 文の引数で宣言された変数はブロック内部で宣言されていると見なせるんでしたね。

//例 3

public class NameSpace{
  public static void main(String[] args){
    for(int i=0;i<3;i++){
      System.out.println(i);
    }
    {int i=10;}
    System.out.println(i);
  }
}


//コンパイル

■D:\atsushi\Java\p192> javac NameSpace.java
NameSpace.java:7: シンボルを解決できません。
シンボル: 変数 i
場所 : NameSpace の クラス
System.out.println(i);
            ^
エラー 1 個

//解説

C言語、C++言語ではちゃんとした意味があるプログラムでも、
Java言語ではただのエラー。
しかし、これは名前の衝突が起きているわけではありません。
これより、ブロック内部で宣言された変数の有効範囲はブロック内部だけである
ということが分かりますね。

//例 4

public class NameSpace{
  int i;
  public static void main(String[] args){
    for(int i=0;i<3;i++){
      System.out.println(i);
    }
  }
}


//実行結果

D:\atsushi\Java\p192>java NameSpace
0
1
2
-- Press any key to exit (Input "c" to continue) --

//解説

メソッド外部と内部で同じ変数を宣言しています。
問題ありません。

//例 5

public class NameSpace{
  public static void main(String[] args){
    for(int i=0;i<3;i++){
      System.out.println(i);
    }
  }
  public static void func(){
    for(int i=4;i<6;i++){
      System.out.println(i);
    }
  }
}


//実行結果

D:\atsushi\Java\p192>java NameSpace
0
1
2
-- Press any key to exit (Input "c" to continue) --

//解説

違うメソッドで同じ変数を宣言しています。
問題ありません。

○まとめ

ブロック内部で宣言された変数の有効範囲はブロック内部だけである。
より内部のブロックであっても同じ変数を宣言することは出来ない。
メソッド内部であれば、メソッド外部と同じ変数を宣言することが出来る。


○補足

変数の初期化を忘れた場合どうなるでしょうか?

public class NameSpace{
  public static void main(String[] args){
    int i;
    System.out.println(i);
  }
}


コンパイラは丁寧(お節介?)にもエラーとして知らせてくれます。
警告ではないので、もちろん実行できません。

■D:\atsushi\Java\p192> javac NameSpace.java
NameSpace.java:4: 変数 i は初期化されていない可能性があります。
System.out.println(i);
            ^
エラー 1 個


戻る / ホーム