Этот интересный и важный вопрос задали одному из моих читателей во время телефонного собеседования на должность Java-разработчика. Хотя он и знал, что сделать абстрактный класс
final
-ьным в языке Java нельзя, его смутила формулировка вопроса. Ответ прост: нет, в final
-классе не может быть абстрактных методов. Почему? А потому, что как только вы объявляете абстрактный метод в классе языка Java, этот класс автоматически становится абстрактным, а сделать абстрактный класс final
’ьным в языке Java нельзя. Значит, абстрактных методов в final
-классе Java быть не может.
Многие Java-разработчики путаются при ответе на этот вопрос из-за формулировки. Даже если человек, которому задали вопрос, знаком с общей концепцией, он может не сообразить, что класс, после объявления в нём абстрактного метода становится абстрактным, а сделать абстрактный класс
final
в языке Java нельзя.
Этот момент отделяет данный вопрос от более распространённого и часто задаваемого вопроса: можно ли в Java объявить класс абстрактным и финальным одновременно?
Рассмотрим один пример кода, чтобы продемонстрировать, что в final
-классе невозможно объявить абстрактный метод. Пусть в Hello.java
у нас есть public final
класс под названием Hello
, в котором есть абстрактный метод print()
.
public final class Hello {
public abstract void print();
}
Наберите этот код в IDE, вы получите следующее сообщение об ошибке, дескать Hello
должен быть абстрактным классом, чтобы в нём можно было объявлять абстрактные методы.
То же самое произойдет, если вы введете этот код в блокноте и скомпилируете его при помощи утилиты javac из командной строки. Согласно спецификациям Java, как только вы объявляете внутри класса абстрактный метод, этот класс становится абстрактным классом, а раз сделать абстрактный класс
final
в Java нельзя, компилятор сгенерирует ошибку.
Это справедливо как для классов верхнего уровня, так и вложенных классов в языке Java. Даже если объявить абстрактный метод во вложенном final
-классе, ошибка будет та же самая.
Еще один вытекающий отсюда вопрос: могут ли у абстрактного класса в языке Java быть статические методы?
Ответ: да, могут, никакой проблемы с объявлением статического метода в абстрактном классе нет, поскольку для использования статического метода не нужно создавать экземпляр класса, их можно вызывать просто при помощи имени класса.
Можно модифицировать наш пример, чтобы включить в класс Hello
метод main()
, являющийся в языке Java статическим, как показано ниже:
public abstract class Hello {
public abstract void print();
public static void main(String args[]) {
// какой-то код
}
}
Как вы можете видеть, никакой ошибки при компиляции не выдается. Этот код компилируется без проблем, поскольку в Java можно совершенно спокойно объявлять статический метод в абстрактном классе.
Краткие выводы
В final
-классе невозможно объявить абстрактный метод. Потому что как только вы это сделаете, класс автоматически становится абстрактным, согласно спецификациям Java. А поскольку final
-класс в Java не может быть абстрактным, это недопустимо, и компилятор запретит вам подобное действие, выдав ошибку. Но объявлять статические методы можно как в final, так и в абстрактных классах, никаких проблем с этим нет.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ