これはインタビューのお気に入りの質問です。この質問で、インタビュアーは、コンストラクター、メソッド、クラス変数(静的変数)、およびインスタンス変数に関して、オブジェクトの動作をどの程度理解しているかを調べます。
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メソッドはオーバーライドできます。(これを文法的に読んでください。このメソッドはサブクラスにあります)