Это любимый вопрос интервью . С помощью этих вопросов интервьюер пытается выяснить, насколько хорошо вы понимаете поведение объектов в отношении конструкторов, методов, переменных класса (статических переменных) и переменных экземпляра.
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
)
Финальные классы не могут быть разделены на подклассы.
Финальные методы не могут быть переопределены. (Этот метод в суперклассе),
финальные методы могут переопределять. (Прочтите это грамматически. Этот метод находится в подклассе)