JavaRush /Java блог /Java Developer /Вопрос-ответ: можно ли в final-классе определить абстракт...

Вопрос-ответ: можно ли в final-классе определить абстрактные методы?

Статья из группы Java Developer
Этот интересный и важный вопрос задали одному из моих читателей во время телефонного собеседования на должность Java-разработчика. Хотя он и знал, что сделать абстрактный класс final-ьным в языке Java нельзя, его смутила формулировка вопроса. Ответ прост: нет, в final-классе не может быть абстрактных методов. Почему? А потому, что как только вы объявляете абстрактный метод в классе языка Java, этот класс автоматически становится абстрактным, а сделать абстрактный класс final’ьным в языке Java нельзя. Значит, абстрактных методов в final-классе Java быть не может.
Вопрос-ответ: можно ли в final-классе определить абстрактные методы? - 1
Многие Java-разработчики путаются при ответе на этот вопрос из-за формулировки. Даже если человек, которому задали вопрос, знаком с общей концепцией, он может не сообразить, что класс, после объявления в нём абстрактного метода становится абстрактным, а сделать абстрактный класс final в языке Java нельзя. Этот момент отделяет данный вопрос от более распространённого и часто задаваемого вопроса: можно ли в Java объявить класс абстрактным и финальным одновременно? Рассмотрим один пример кода, чтобы продемонстрировать, что в final-классе невозможно объявить абстрактный метод. Пусть в Hello.java у нас есть public final класс под названием Hello, в котором есть абстрактный метод print().

public final class Hello {
  public abstract void print();
}
Наберите этот код в IDE, вы получите следующее сообщение об ошибке, дескать Hello должен быть абстрактным классом, чтобы в нём можно было объявлять абстрактные методы.
Вопрос-ответ: можно ли в final-классе определить абстрактные методы? - 2
Вопрос-ответ: можно ли в final-классе определить абстрактные методы? - 3
То же самое произойдет, если вы введете этот код в блокноте и скомпилируете его при помощи утилиты 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, так и в абстрактных классах, никаких проблем с этим нет.
Комментарии (6)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Марат Гарипов Уровень 108 Expert
14 июня 2022
Ни в коем случае не спорю, и согласен, с тем, что объявить абстрактные методы в final-классе нельзя - это понятно. Но ведь вопрос в заглавии статьи был: можно ли в final-классе ОПРЕДЕЛИТЬ абстрактные методы?) мне показалось, что подвох именно в этом) Ведь определить не есть объявить. Если бы мне задали такой вопрос, то я бы уточнил, как раз этот момент. Ведь final-класс может быть наследником абстрактного класса с абстрактными методами, которые хочешь-не хочешь придется переОПРЕДЕЛЯТЬ в классе-наследнике - а это как раз наш final-класс)
Vadim Karavayev Уровень 31
19 января 2018
А если так final public class FinalDemo { abstract class A { public abstract void doIt(); } } файнал класс есть, в нем абстрактный метод есть. public static void main(String[] args) { FinalDemo fd = new FinalDemo(); FinalDemo.A a = fd.new A() { @Override public void doIt() { System.out.println("Hang in there!"); } }; a.doIt(); }