これはインタビューのお気に入りの質問です。この質問で、インタビュアーは、コンストラクター、メソッド、クラス変数(静的変数)、およびインスタンス変数に関して、オブジェクトの動作をどの程度理解しているかを調べます。
import java.util.ArrayList;
import java.util.List;
class Test {
private final List foo;
public Test() {
foo = new ArrayList();
foo.add("foo"); // Modification-1
}
public void setFoo(List foo) {
//this.foo = foo; Results in compile time error.
}
}
上記の例では、「Test」のコンストラクタを定義し、「setFoo」メソッドを指定しています。
コンストラクターについて:コンストラクターは、キーワードを使用して、オブジェクトの作成ごとに1回だけ呼び出すことができますnew
。コンストラクターはそのように設計されていないため、コンストラクターを複数回呼び出すことはできません。
メソッドについて:メソッドは何度でも(絶対に)呼び出すことができ、コンパイラーはそれを認識します。
シナリオ1
private final List foo; // 1
foo
あるインスタンス変数は。Test
クラスオブジェクトを作成すると、インスタンス変数foo
がTest
クラスのオブジェクト内にコピーされます。foo
コンストラクター内で割り当てる場合、コンパイラーはコンストラクターが1回だけ呼び出されることを認識しているため、コンストラクター内で割り当てることは問題ありません。
メソッド内
で割り当てる場合foo
、コンパイラーはメソッドを複数回呼び出すことができることを知っています。つまり、値は複数回変更する必要があり、final
変数では許可されません。したがって、コンパイラーはコンストラクターが良い選択であると判断します!最終変数に値を割り当てることができるのは1回だけです。
シナリオ2
private static final List foo = new ArrayList();
foo
現在は静的変数です。Test
クラスのインスタンスを作成すると、静的であるfoo
ため、オブジェクトにコピーされませんfoo
。現在foo
、各オブジェクトの独立したプロパティではありません。これはTest
クラスのプロパティです。しかしfoo
、複数のオブジェクトから見ることができ、複数のオブジェクトの作成時に値を変更するコンストラクターをnew
最終的に呼び出すキーワードを使用して作成されたすべてのオブジェクト(すべてのオブジェクトにコピーされるのではなく、複数のオブジェクト間で共有されることをTest
思い出してくださいstatic foo
) 。)
シナリオ3
t.foo.add("bar"); // Modification-2
上記Modification-2
はあなたの質問からです。上記の場合、最初に参照されるオブジェクトを変更するのではなく、foo
許可されているコンテンツを内部に追加します。あなたが割り当てしようとした場合、コンパイラは文句を言いnew ArrayList()
にfoo
参照変数。
ルールfinal
変数を初期化した場合、別のオブジェクトを参照するように変数を変更することはできません。(この場合ArrayList
)
finalクラスはサブクラス化できません
finalメソッドはオーバーライドできません。(このメソッドはスーパークラスにあります)
finalメソッドはオーバーライドできます。(これを文法的に読んでください。このメソッドはサブクラスにあります)