50542

[code]

    public class ClassN {
        public static void main(String[] args) {
            Person[] persons = { new Person(), new Person(), new Person()};
    
            persons[0].setData("Oshima", 30);
            persons[1].setData("Murakami", 30);
            persons[2].setData("Kurosawa", 32);
    
            for (int i = 0; i < persons.length; i++) {
                persons[i].introduce();
            }
    
            System.out.println();
    
            persons[0].compare(persons[1]);
            persons[1].compare(persons[2]);
            persons[2].compare(persons[1]);
        }
    
        class Person {
            private String name;
            private int age;
    
    
            public void setData(String pname, int page) {
                name = pname;
                age = page;
            }
    
            public int getAge() {
                return age;
            }
    
            public String getName() {
                return name;
            }
    
            public void introduce() {
                System.out.println("I am" + name + " and I am " + age + "years old.");
            }
    
            public void compare(Person person) {
                if (age == person.getAge()) {
                    System.out.println(name + "and" + person.getName() + "are same old.");
                } else if (age < person.getAge()) {
                    System.out.println(name + "is younger than " + person.getAge() + "for" + (person.getAge() - age) + "year");
                } else {
                    System.out.println(name + "is older than " + person.getAge() + "for" + (age - person.getAge()) + "year");
                }
    
            }
        }
    }
    
[/code]

このコードを入れると  
3行目のnew Person()の三つに  
staticでない変数 thisをstaticコンテキストから参照することはできません  
というエラーがでます。

サンプルコードを写経して、間違いないつもりなのですが間違っている箇所があるのでしょうか？  
staticフィールドとインスタンスフィールドの違いは理解できているのではないかと思うのですが、staticフィールドを参照してる箇所が思いつかず、詰まっています。


CC BY-SA 4.0
2018-11-21T12:03:12.973
50511
2018-11-22T12:38:26.480
31098
question
java
インスタンス作成時のstaticフィールドについて


Javaの(`static`でない)内部クラスの特殊な取り扱いに引っかかっているようです。

まずはあなたのコードの全体の概略構造を見てみましょう。

[code]

    class ClassN {
        //...
    
        class Person {
            //...
        }
    }
    
[/code]

すでに分かっておられるかもしれませんが、`Person`クラスは`ClassN`クラスの内部にネストされた(`static`でない)内部クラスです。

Javaの(`static`でない)内部クラスでは、外側のクラスのインスタンス変数にアクセス出来たりするのですが、それを実現するためにJavaのコンパイラは、かなり特殊なことをします。

具体的に言うと、

  * 見えないインスタンス変数`outerThis`を追加する (*)
  * 全てのコンストラクタに`outerThis`を受け取る見えない引数を追加する
  * 全てのコンストラクタ呼び出しで(つまりここは呼び出し側)、見えない引数に`this`(外側のクラスのインスタンス)を渡す

なんてことが、コードに記載されていないのに行われてしまいます。

(*)のインスタンス変数名は仮称

Javaのコンパイラ内部ではこんな感じに扱われるわけです。

[code]

    class ClassN {
        //...
    
        class Person {
            //...
            private ClassN outerThis; //コンパイラ内部だけに見えるインスタンス変数
    
            //コンパイラが自動生成したデフォルトコンストラクタ
            //`outerThis`引数は呼び出し側からは見えない
            public Person(ClassN outerThis) {
                this.outerThis = outerThis;
            }
        }
    }
    
[/code]

これに対して、`new Person()`と言うコンストラクタ呼び出しは、コンパイラ内部では、`new
Person(this)`と扱われ、コンストラクタ`Person(ClassN)`の第一引数に暗黙のうちに外側クラス`ClassN`のインスタンスが渡されます。

つまり、あなたの`main`内部でのこの行:

[code]

        Person[] persons = { new Person(), new Person(), new Person()};
    
[/code]

は、Javaコンパイラにはこのように扱われているのです。

[code]

        Person[] persons = { new Person(this), new Person(this), new Person(this)};
    
[/code]

`static`メソッドである`main`メソッドの内部は全て`static`コンテキストですから、その内部での`this`の使用が「staticでない変数
thisをstaticコンテキストから参照することはできません」と言うエラーになっています。

* * *

元のサンプルコードが本当はどんなものだったのかはわかりませんが、一番手っ取り早くエラーを解消するには、内部クラスを`static`宣言するのが早いでしょう。

[code]

    class ClassN {
        //...
    
        static class Person { //<- 内部クラスは`static`宣言する
            //...
        }
    }
    
[/code]

こうすることで、Javaコンパイラは、内部クラスから外側クラスのインスタンスにアクセスするための隠しフィールドや隠し引数は不要と判断するので、暗黙のうちに`this`が渡されることもなくなり、コンパイルは通るはずです。

* * *

他にも、`Person`を内部クラスとせず、独立した`Person.java`に定義してしまうと言うやり方もあるでしょう。現在ではJavaの(`static`でない)内部クラスは、「機能としてはあるけど使っちゃいけないもの」と言うのがかなり共通した認識です。参考にされた書籍やサイトが、本当に一言一句ご質問のままのサンプルコードを載せていたのなら、その書籍(サイト)は、あまり信頼できそうにないですね。


CC BY-SA 4.0
2018-11-21T12:52:07.960
50513
2018-11-21T12:52:07.960
13972
50511
answer


`public class ClassN {`のカッコの閉じ忘れでしょう。  
その上で、つじつまを合わせるために最後に閉じカッコを付けたため、参照しているコードと異なる結果になっているのだと考えます。

* * *
[code]

    class Person {
    
[/code]

の直前行に `}` を挿入し、代わりに最終行の `}` を削除すればコンパイルが通り、実行すれば想定された結果が得られるかと思います。


CC BY-SA 4.0
2018-11-22T12:38:26.480
50542
2018-11-22T12:38:26.480
2808
50511
answer