Это любимый вопрос интервью . С помощью этих вопросов интервьюер пытается выяснить, насколько хорошо вы понимаете поведение объектов в отношении конструкторов, методов, переменных класса (статических переменных) и переменных экземпляра.
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.
О конструкторе: конструктор можно вызывать только один раз за создание объекта с помощью newключевого слова. Вы не можете вызывать конструктор несколько раз, потому что конструктор не предназначен для этого.
О методе: метод может вызываться столько раз, сколько вы хотите (даже никогда), и компилятор знает это.
Сценарий 1
private final List foo; // 1
fooэто экземпляр переменной. Когда мы создаем Testобъект класса, тогда переменная экземпляра fooбудет скопирована внутри объекта Testкласса. Если мы присваиваем fooвнутри конструктора, то компилятор знает, что конструктор будет вызываться только один раз, поэтому нет проблем с его назначением внутри конструктора.
Если мы присваиваем fooвнутри метода, компилятор знает, что метод может быть вызван несколько раз, что означает, что значение придется менять несколько раз, что недопустимо для finalпеременной. Таким образом, компилятор решает, что конструктор - хороший выбор! Вы можете присвоить значение конечной переменной только один раз.
Сценарий 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)
Финальные классы не могут быть разделены на подклассы.
Финальные методы не могут быть переопределены. (Этот метод в суперклассе),
финальные методы могут переопределять. (Прочтите это грамматически. Этот метод находится в подклассе)