1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java Gold SE11対策 ネストしたクラスシリーズ③ ローカルクラスについて

Posted at

前回の記事
Java Gold SE11対策 ネストしたクラスシリーズ② staticインナークラスについて
の続きとして本記事では「ローカルクラス」についてまとめていく。

ローカルクラスはメソッド内に定義されるもの

メソッド内に定義されるクラスがローカルクラスである。
ローカルクラスは定義されているメソッド内のみから利用することができる。

そのため、同じクラスでも別のメソッドからローカルクラスを利用することはできない。
これはローカル変数を別メソッドが利用できないのと同じだ。

下のSample.javaのsampleMethodメソッドのAgeクラスがローカルクラスである。

Sample.java
public class Sample {
   // ローカルクラスを実装したメソッド
   void sampleMethod() {
      int age = 30;

      // ローカルクラス
      class Age{
         public void printAge() {
            System.out.println(age + "歳ですよ。");
         }  
      }

      // ローカルクラスへのアクセスと実行
      Age ageClass = new Age();
      ageClass.printAge();
   }
}

ローカルクラスの付与可能なアクセス修飾子

ローカルクラスは前項でも説明した通り、それを定義したメソッドからしかアクセスができない。他のクラスから利用できないというのは言うまでもない。

そのため下記のアクセス修飾子をローカルクラスに付与することはできない。
public
protected
private

一方でabstractを付けて抽象クラスにしたり、finalで修飾することは可能だ。

ローカル変数

ローカルクラスはそれを定義したメソッド内のローカル変数にアクセスすることができる。
改めて先ほど例に使用したSampleクラスを見ていただきたい。

ローカルクラスAgeでは、sampleMethodメソッド内のageというローカル変数を利用している。

Sample.java
public class Sample {
   // ローカルクラスを実装したメソッド
   void sampleMethod() {
      int age = 30;

      // ローカルクラス
      class Age{
         public void printAge() {
            System.out.println(age + "歳ですよ。");
         }  
      }

      // ローカルクラスへアクセスと実行
      Age ageClass = new Age();
      ageClass.printAge();
   }
}

ただし、ローカルクラスから利用できるローカル変数には条件がある。

まずローカルクラスよりも前に宣言されていることだ。
先ほどの例でいうと、仮にローカル変数ageがローカルクラスよりも後に宣言されていたらコンパイルエラーが発生する。

もう一つの条件は実質的finalであることだ。
次の例ではsampleMethodメソッドのローカルクラスの後にローカル変数ageを40に変更しているが、
この時点で値が変わっておりfinalな変数ではなくなって、コンパイルエラーが発生する。

Sample.java
public class Sample {
   // ローカルクラスを実装したメソッド
   void sampleMethod() {
      int age = 30;

      // ローカルクラス
      class Age{
         public void printAge() {
            System.out.println(age + "歳ですよ。");
         }  
      }

      age = 40;

      // ローカルクラスへアクセスと実行
      Age ageClass = new Age();
      ageClass.printAge();
   }
}

これはローカル変数とローカルクラスのライフサイクルの違いによるものだ。
ローカル変数はメソッドの処理が終了するとメモリから消えてなくなるのに対し、
ローカルクラスのインスタンスはメソッドの処理が終了しても参照が残っていればメモリ上に存在し続ける。

このようにライフサイクルが異なるので、ローカルクラスが必要としているのに、メモリ上にそのローカル変数が存在していなかったらアクセスができなくなってしまう。なんてことも起きうるのだ。

そのようなことが起きないために、ローカルクラスにはそのローカル変数そのものではなく、ローカル変数の値のコピーを渡している。
コピーを渡していればローカルクラスが必要としているタイミングでローカル変数そのものがメモリ上から消えていても同じ値を持つためローカルクラスは正常に動作する。

しかし、正常に動作するのはコピーした値がお目当てのローカル変数と同じ値である ということが大前提。
そのためローカル変数の値を別の値に変えるような処理が存在すると、コピーした値と変更後のローカル変数の間で不整合が発生してコンパイルエラーが起きるのだ。

次回は匿名クラスについてまとめる。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?