これはお気に入りのインタビューの質問です。この質問を使用して、インタビュアーは、コンストラクター、メソッド、クラス変数(静的変数)、およびインスタンス変数に関するオブジェクトの動作をどの程度理解しているかを調べようとします。
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
Nowfoo
は、各オブジェクトの独立したプロパティではありません。これはTest
クラスのプロパティです。ただし、複数のオブジェクトで確認でき、キーワードをfoo
使用して作成されたすべてのオブジェクトが、複数のオブジェクトの作成時に値を変更するコンストラクターを最終的に呼び出す場合(すべてのオブジェクトでコピーされるわけではなく、複数のオブジェクト間で共有されることを忘れないでください) 。)new
Test
static foo
シナリオ3
t.foo.add("bar"); // Modification-2
上記Modification-2
はあなたの質問からです。上記の場合、最初に参照されるオブジェクトを変更するのではなく、foo
許可されているコンテンツを内部に追加します。参照変数new ArrayList()
にを割り当てようとすると、コンパイラは文句を言います。ルール変数を初期化した場合、別のオブジェクトを参照するように変数を変更することはできません。(この場合)foo
final
ArrayList
最終クラスをサブクラス化することはできません。
最終メソッドをオーバーライドすることはできません。(このメソッドはスーパークラスにあります)
finalメソッドはオーバーライドできます。(これを文法的に読んでください。このメソッドはサブクラスにあります)