サーチ…


備考

これは "Null Pointer Exception"を理解するのに役立つはずです。オブジェクト参照がnullなので、そのうちの1つを取得しますが、プログラムコードはそのオブジェクト参照で何かを使用することを期待しています。しかし、それは独自のトピックに値する...

メソッドパラメータとしてのオブジェクト参照

このトピックでは、 オブジェクト参照の概念について説明します 。 Javaでプログラミングを初めて経験した人を対象にしています。クラス定義、メインメソッド、オブジェクトインスタンス、オブジェクトの "on"メソッドの呼び出し、メソッドへのパラメータの渡しなど、いくつかの用語と意味に慣れているはずです。

public class Person {

  private String name;

  public void setName(String name) { this.name = name; }

  public String getName() { return name; }

  public static void main(String [] arguments) {
    Person person = new Person();
    person.setName("Bob");

    int i = 5;
    setPersonName(person, i);

    System.out.println(person.getName() + " " + i);
  }

  private static void setPersonName(Person person, int num) {
    person.setName("Linda");
    num = 99;
  }
}

Javaプログラミングを十分に理解するためには、この例をあなたの頭の上の誰かに説明することができます。その概念は、Javaの仕組みを理解する上で基本的なものです。

ご覧のように、変数personオブジェクトをインスタンス化するmainがあり、そのオブジェクトのnameフィールドを"Bob"に設定するメソッドを呼び出します。次に、別のメソッドを呼び出し、 personを2つのパラメータの1つとして渡します。もう1つのパラメータは5に設定された整数変数です。

呼び出されたメソッドは、渡されたオブジェクトのname値を "Linda"に設定し、渡された整数変数を99に設定してから戻ります。

では、何が印刷されるのですか?

Linda 5

だから、なぜpersonなされた変更がmainに反映されるのですか?整数に加えられた変更はなぜですか?

呼び出しが行われると、mainメソッドはperson オブジェクト参照setPersonNameメソッドにsetPersonNameます。 setAnotherNameがそのオブジェクトに対して行う変更はそのオブジェクトの一部であり、メソッドが戻るときにそれらの変更はそのオブジェクトの一部です。

同じことを言うもう一つの方法: personはオブジェクト(ヒープに保存されている場合は、興味があれば)を指します。メソッドがそのオブジェクトに対して行う変更は、そのオブジェクトに対して行われ、変更を行うメソッドがまだアクティブであるか返されたかによって影響を受けません。メソッドが復帰すると、オブジェクトに加えられた変更はすべてそのオブジェクトに保存されます。

渡された整数とこれを比較してください。これはプリミティブ int(Integerオブジェクトインスタンスではない)なので、渡された "値によって"、その値はメソッドに渡され、渡された元の整数へのポインタではありません。メソッドは、しかし、それはメソッド呼び出しが行われたときに使用される変数には影響しません。

Javaでは、すべてのプリミティブが値渡しされます。オブジェクトは参照渡しされます。つまり、オブジェクトへのポインタが、それらを受け取るメソッドにパラメータとして渡されます。

明らかではないことは、呼び出されたメソッドが新しいオブジェクトを作成し、それをパラメータの1つとして返すことは不可能であることを意味します。メソッドがメソッド呼び出しによって直接的または間接的に作成されたオブジェクトを返す唯一の方法は、メソッドの戻り値としてです。最初にそれがどうやってうまくいかないのか、どうしたらうまくいくのかを見てみましょう。

私たちの小さな例にもう一つの方法を追加しましょう:

private static void getAnotherObjectNot(Person person) {
  person = new Person();
  person.setName("George");
}

mainに戻り、 setAnotherNameの呼び出しの下で、このメソッドともう1つのprintln呼び出しを呼び出しましょう:

getAnotherObjectNot(person);
System.out.println(person.getName());

今度はプログラムが出力します:

Linda 5
Linda

ジョージを持っていたオブジェクトには何が起こったのですか?さて、渡されたパラメータはLindaへのポインタでした。 getAnotherObjectNotメソッドが新しいオブジェクトを作成したとき、それはLindaオブジェクトへの参照をGeorgeオブジェクトへの参照に置き換えました。 Lindaオブジェクトはまだ(ヒープ上に)存在していますが、 mainメソッドはまだそれにアクセスできますが、 getAnotherObjectNotメソッドはそれへの参照がないため、その後は何もできません。コードの作者は、新しいオブジェクトを作成して戻す方法を意図していたようですが、そうであれば機能しませんでした。

それが作者がやりたいことであれば、メソッドから新しく作成されたオブジェクトを返す必要があります。

private static Person getAnotherObject() {
  Person person = new Person();
  person.setName("Mary");
  return person;
}

それからこれを次のように呼んでください:

Person mary;
mary = getAnotherObject();
System.out.println(mary.getName());

プログラム全体の出力は次のようになります。

Linda 5
Linda
Mary

両方の追加があるプログラム全体がここにあります:

public class Person {
  private String name;

  public void setName(String name) { this.name = name; }
  public String getName() { return name; }

  public static void main(String [] arguments) {
    Person person = new Person();
    person.setName("Bob");

    int i = 5;
    setPersonName(person, i);
    System.out.println(person.getName() + " " + i);
    
    getAnotherObjectNot(person);
    System.out.println(person.getName());
    
    Person person;
    person = getAnotherObject();
    System.out.println(person.getName());
  }
  
  private static void setPersonName(Person person, int num) {
    person.setName("Linda");
    num = 99;
  }
  
  private static void getAnotherObjectNot(Person person) {
    person = new Person();
    person.setMyName("George");
  }
  
  private static person getAnotherObject() {
    Person person = new Person();
    person.setMyName("Mary");
    return person;
  }
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow