Java 変数のスコープ(有効範囲)


この記事は、他の言語でプログラミングしていた人が、Javaでプログラムを組んでみると言う人に向けて書いた記事です。

スコープとは

スコープとは使える範囲のことです。変数に限らず有効範囲をスコープと言います。今回は変数のスコープについての実例を記載します。
例1)

このように、mainからchainの変数を直接持ってくることはできません。
つまり、chainのiのスコープはchain内、mainのiのスコープはmain内ということです。
例2)

if文の中で宣言した値はif文内のみで使用できます。もし他でも使用したい場合は、if文のそとで宣言した値をif文内で操作するように変更すれば問題ありません。

グローバル変数とローカル変数

変数にはグローバル変数とローカル変数の2つがあります。
ローカル変数はこれまで出てきたように範囲内でしか使えない値(=スコープが有限)です。それに対してグローバル変数はスコープに制限のない変数です。Javaにはグローバル変数そのものは存在しませんが、グローバル変数と同じ状態にすることができます。
記載方法は public static 変数の記載 です。
例)

グローバル変数はどこからでも参照できるので、他のクラスなどから値の変更などができます。影響度が非常に大きいので、必要な時のみ使うようにして、できるかぎりローカル変数を使いましょう。

public と static

グローバル変数は public static 変数の記載 と書くと記載しましたが、
それはこのpublic と static の2つがそれぞれ使える箇所(スコープ)を拡張するからです。この2点についても説明します。

アクセス修飾子

publicはアクセス修飾子というものの1つです。
一つずつあげていきます。
・public(公的な)は制限をつけません。
・protected(保護された) はクラスか、クラスを継承したサブクラス内部からのみアクセスを許可します。
・何もつけない場合は、同じパッケージ内のすべてのクラスからアクセスできます。
・private(私的) はクラス内部からのみ、アクセスが可能です。

このうちprotected変数以外では動きが確認できましたが、protectedの動きが想定外だったため、一旦protected以外の条件です。
確認用プログラム

practice.java

class Main {
  public static String pubstr = "公的";
  protected static String prostr = "保護された";
  static String str = "なし";
  private static String pristr = "私的";

  public static void main(String[] args) {
    System.out.println(pubstr); // 公的
    System.out.println(str); // なし
    System.out.println(pristr); // 私的

    check();
    Sub subclass = new Sub();
    subclass.sub();
  }

  public static void check() {
    System.out.println(pubstr); // 公的
    System.out.println(str); // なし
    System.out.println(pristr); // 私的
  }
}

class Sub {
  public void sub() {
    Main m = new Main();
    System.out.println(m.pubstr); // 公的
    System.out.println(m.str); // なし
    System.out.println(m.pristr); // privateは取得できないのでエラー
  }
}
static

static(静的な)とは、staticメソッド(staticがついているメソッド)にでも使用可能にするものです。具体例を表示します。

practice.java
class Main {
  public int ni = 10;
  public static int si = 7;
  int di = 999;

  public static void main(String[] args) {
    System.out.println(ni); // niはstatic変数でないのでエラー
    System.out.println(si); // siはstatic変数なので7が出力
  }

  public void check(String[] args) {
    System.out.println(ni); // checkはstaticメソッドでないので10が出力
    System.out.println(si); //checkはstaticメソッドでないので7が出力
  }
}

このように、staticとついたメソッドではstaticのついた変数のみ使用可能です。