今日もJava Silver試験に向けて問題に挑戦してみましょう!
問題
以下のプログラムを実行すると、どのような結果が出力されるでしょうか? 適切な選択肢を選んでください。
public class Plant {
private String type;
Plant(String type) {
this.type = type;
}
void printType() {
System.out.println("Type: " + type);
}
public static void main(String[] args) {
Plant flower = new Plant("Flower");
Plant tree = flower;
tree.printType();
flower = null;
tree.printType();
tree = null;
System.gc();
}
}
選択肢
- A. Type: Flowerが2回表示される
- B. Type: Flowerが1回表示され、その後NullPointerExceptionが発生する
- C. コンパイルエラー
- D. プログラムが正常に終了して出力なし
答えと解説
回答を見る
答え
A. Type: Flowerが2回表示される
解説
この問題はJavaのオブジェクトのライフサイクルとガベージコレクションの理解を問うものです。
はじめに、変数flower
とtree
は同じ”Flower”というオブジェクトを参照しています。
そのため、最初のtree.printType()
の呼び出しでは「Type: Flower」と出力されます。
flower
にnullを代入してもtree
はオブジェクトを参照し続けるため、再びtree.printType()
を呼び出しても「Type: Flower」と出力されます。
プログラムの終わりでtree
にもnullを代入してガベージコレクションを試みていますが、これはガベージコレクションを強制するものではありません。
したがって、出力は「Type: Flower」が2回表示されます。
基本説明
Javaのオブジェクトはヒープメモリに格納され、参照型変数がそれを指します。
一旦オブジェクトを指している変数がなくなれば、そのオブジェクトはガベージコレクションの対象になります。
しかし、ガベージコレクションのタイミングは非決定論的であり、プログラムが強制的に実行できるものではありません。
System.gc()
はガベージコレクトを試みるだけで、その実行が保証されるわけではありません。
誤答理由
選択肢Bと同様のNullPointerExceptionが発生しないのは、tree
変数がnullになる前にtree.printType()
が呼ばれているためです。
コンパイルエラーは発生しません。変数参照が正しいためです。
つまずきポイント
初心者は、nullの影響範囲やオブジェクトの参照の仕組みで混乱することがあります。
オブジェクトへの参照が別の参照にコピーされても、それは同じオブジェクトを指し続けることを理解することが重要です。
発展知識
Javaのガベージコレクターは、ヒープ内オブジェクトの寿命を管理しますが、このプロセスは非決定的です。
プログラムの効率化を図るため、ガベージコレクションに依存しすぎないメモリ管理を心がけましょう。