変数名の重複 - 変数のスコープ - 萌えJava超入門
第十三章 変数とスコープ

変数名の重複

変数名が重複した場合のルールをまとめました。
でも可能な限り重複を避けましょう。

目次



1.クラス変数名とローカル変数名は重複できる

変数名の重複に関するルール
  1. 同一のクラス内であっても異なるメソッドであれば、同名の変数を宣言できます。
    (それぞれのスコープが重複しない為)
  2. 基本的には、同一のメソッド内では同名の変数を宣言できません。
    ただし、スコープが重複しない場合には例外もあります。→ 次ページより解説
  3. クラス変数とローカル変数は、変数名が同じでも別の変数として扱われます。
  4. 同名のクラス変数とローカル変数のスコープが重なる場合には、
    ローカル変数が優先されます。
  5. 特にクラス変数を参照したい場合には、クラス名.変数名と表記します。

あ~。
私の脳みそって言語野が弱いんスかね。
そうなの?
今度見せて。



わざと重複した変数名をつけて
実験してみよう!
Sample08_028.java(お勧めできないソースコード)
//Sample08_028.java
class Sample08_028{

  static int num_01 = 999;//クラス変数

  static int method_01(){
    int num_01 = 20;
    return num_01;//ローカル変数を返します
  }

  static int method_02(){
    return num_01;//クラス変数を返します
  }

  static int method_03(){
    int num_01 = 30;
    return Sample08_028.num_01;//クラス変数を返します
  }

  public static void main(String[] args){
    int number;

    number = num_01;// Sample08_028.num_01;の方がわかりやすい
    System.out.println("class_var: " + number);

    number = method_01();
    System.out.println("method_01: " + number);

    number = method_02();
    System.out.println("method_02: " + number);

    number = method_03();
    System.out.println("method_03: " + number);

  }
}


コマンドライン
>javac Sample08_028.java
>java Sample08_028
class_var: 999
method_01: 20
method_02: 999
method_03: 999

Sample08_028 の説明
  1. Sample08_028では、クラス変数を含めて3つの「int num_01」が宣言されています。
    これらはすべて別の変数として扱われます。
  2. mainメソッドの最初 number = num_01 では、mainメソッドにローカル変数の num_01 が無いのでクラス変数の num_01として扱われました。
  3. method_01 はローカル変数を持っているので、ローカル変数の num_01を返しました。
  4. method_02 はローカル変数を持っていないので、クラス変数の num_01を返します
  5. method_03 はローカル変数がありますが、クラス変数を指定しているのでクラス変数の num_01を返しました。
変数名が重複しているがちゃんと動く。
でもこれはとても危険な状態だ。


2.クラス変数名とローカル変数名の重複は危険


Sample08_028.javaは、動作を検証するため実験的に書いたコードですが、
クラス変数名とローカル変数名の重複は非常に危険です。
例えば、Sample08_028.javaの method_01を、以下の method_04の様に間違ってしまうと...。

Sample08_029.java(変数取り違えの例)
//Sample08_029.java
class Sample08_029{

  static int num_01 = 999;//クラス変数

  static int method_04(){
    /*
    * うっかりローカル変数の宣言を忘れると!!
    */
    //int num_01 = 20;
    return num_01;//クラス変数を返します
  }

  public static void main(String[] args){
    int number;

    number = num_01;
    System.out.println("class_var: " + number);

    number = method_04();
    System.out.println("method_04: " + number);

  }
}



コマンドライン
>javac Sample08_029.java
>java Sample08_029
class_var: 999
method_04: 999 ←期待値は 20


Sample08_029の説明
Sample08_029は、クラス変数とローカル変数を取り違える典型的な例です。
method_04にローカル変数を宣言したつもりが、何かの拍子で消してしまうと...。
クラス変数とローカル変数の重複がなければ、エラーになるのですが、
同名のクラス変数がカバーしてしまうため、エラーは発生しません。
コードの誤りに気づきにくいのです。

このチュートリアルで推奨するルール
メンバ変数とローカル変数の名前の重複だけは避けましょう。

メンバ変数だけ気をつけて命名すれば
エラーでわかる。
//Sample08_030.java
class Sample08_030{

  static int init_value = 999;

  static int method_04(){
    /*
    * うっかりローカル変数の宣言を忘れても
    */
    //int num_01 = 20;
    return num_01;
  }

  public static void main(String[] args){
    int number;

    number = init_value;
    System.out.println("class_var: " + number);

    number = method_04();
    System.out.println("method_04: " + number);

  }
}


コマンドライン
>javac Sample08_030.java
Sample08_030.java:8: エラー: シンボルを見つけられません
                return num_01;
                       ^
  シンボル:   変数 num_01
  場所: クラス Sample08_030
エラー1個

今度はちゃんとエラーになったな。



間違っているところでエラーが出るような
書き方が良いってことっすね。

なるほどね。


お疲れ様でした。




© 2019 awasekagami