- Java абстрактный класс может быть final
- 10 вопросов по абстрактным классам и интерфейсам с собеседований по Java
- 1. Могут ли в языке Java у абстрактного класса быть конструкторы?
- 2. Могут ли абстрактные классы в языке Java реализовывать интерфейсы? Должны ли они реализовывать все методы?
- 3. Может ли абстрактный класс быть final?
- 4. Могут ли у абстрактного класса в языке Java быть статические методы?
- 5. Можно ли создать экземпляр абстрактного класса?
- 6. Обязательно ли в абстрактном классе должны быть абстрактные методы?
- 7. Каковы различия между абстрактным классом и интерфейсом в Java?
- 8. Когда имеет смысл предпочесть абстрактный класс интерфейсу и наоборот?
- 9. Что такое абстрактный метод в языке Java?
- 10. Может ли абстрактный класс в Java содержать метод main ?
Java абстрактный класс может быть final
Class declarations define new reference types and describe how they are implemented (§8.1).
A top level class is a class that is not a nested class.
A nested class is any class whose declaration occurs within the body of another class or interface.
This chapter discusses the common semantics of all classes — top level (§7.6) and nested (including member classes (§8.5, §9.5), local classes (§14.3) and anonymous classes (§15.9.5)). Details that are specific to particular kinds of classes are discussed in the sections dedicated to these constructs.
A named class may be declared abstract (§8.1.1.1) and must be declared abstract if it is incompletely implemented; such a class cannot be instantiated, but can be extended by subclasses. A class may be declared final (§8.1.1.2), in which case it cannot have subclasses. If a class is declared public , then it can be referred to from other packages. Each class except Object is an extension of (that is, a subclass of) a single existing class (§8.1.4) and may implement interfaces (§8.1.5). Classes may be generic (§8.1.2), that is, they may declare type variables whose bindings may differ among different instances of the class.
Classes may be decorated with annotations (§9.7) just like any other kind of declaration.
The body of a class declares members (fields and methods and nested classes and interfaces), instance and static initializers, and constructors (§8.1.6). The scope (§6.3) of a member (§8.2) is the entire body of the declaration of the class to which the member belongs. Field, method, member class, member interface, and constructor declarations may include the access modifiers (§6.6) public , protected , or private . The members of a class include both declared and inherited members (§8.2). Newly declared fields can hide fields declared in a superclass or superinterface. Newly declared class members and interface members can hide class or interface members declared in a superclass or superinterface. Newly declared methods can hide, implement, or override methods declared in a superclass or superinterface.
Field declarations (§8.3) describe class variables, which are incarnated once, and instance variables, which are freshly incarnated for each instance of the class. A field may be declared final (§8.3.1.2), in which case it can be assigned to only once. Any field declaration may include an initializer.
Member class declarations (§8.5) describe nested classes that are members of the surrounding class. Member classes may be static , in which case they have no access to the instance variables of the surrounding class; or they may be inner classes (§8.1.3).
Member interface declarations (§8.5) describe nested interfaces that are members of the surrounding class.
Method declarations (§8.4) describe code that may be invoked by method invocation expressions (§15.12). A class method is invoked relative to the class type; an instance method is invoked with respect to some particular object that is an instance of a class type. A method whose declaration does not indicate how it is implemented must be declared abstract . A method may be declared final (§8.4.3.3), in which case it cannot be hidden or overridden. A method may be implemented by platform-dependent native code (§8.4.3.4). A synchronized method (§8.4.3.6) automatically locks an object before executing its body and automatically unlocks the object on return, as if by use of a synchronized statement (§14.19), thus allowing its activities to be synchronized with those of other threads (§17 (Threads and Locks)).
Method names may be overloaded (§8.4.9).
Instance initializers (§8.6) are blocks of executable code that may be used to help initialize an instance when it is created (§15.9).
Static initializers (§8.7) are blocks of executable code that may be used to help initialize a class.
Constructors (§8.8) are similar to methods, but cannot be invoked directly by a method call; they are used to initialize new class instances. Like methods, they may be overloaded (§8.8.8).
10 вопросов по абстрактным классам и интерфейсам с собеседований по Java
Абстрактные классы и интерфейсы очень популярны во всех объектно-ориентированных языках программирования. И практически на каждом собеседовании по Java попадается хотя бы один вопрос на эту тему. Интерфейсы упоминаются чаще, из-за их популярности среди проектировщиков ПО, но время от времени встречаются и вопросы по абстрактным классам. Последние чаще задают претендентам на должность джуниор-разработчиков, скажем, с не более чем двухлетним опытом разработки на Java, в то время как вопросы по интерфейсам чаще всего встречаются при собеседовании тех, чей опыт уже перевалил за четыре года. В основном, их задают вместе с другими вопросами по паттернам проектирования Java, например, по паттернам Decorator (Декоратор) или Factory (Фабрика). В этой статье мы рассмотрим частые вопросы по абстрактным классам и интерфейсам, которые задавались на собеседованиях по Java разного уровня. Большинство из них не должно представлять сложности даже для начинающего Java-программиста. В основном это вопросы на чистое знание, но некоторые из них, например, о различиях между абстрактными классами и интерфейсами в Java или о том, когда лучше предпочесть абстрактный класс интерфейсу, могут оказаться достаточно непростыми. Предлагаем вам десяток интересных вопросов по теме.
Если вам когда-либо задавали на собеседовании или приходилось задавать какой-либо стоящий внимания вопрос об абстрактных классах и интерфейсах, но его в данном списке нет, делитесь им в комментариях. |
1. Могут ли в языке Java у абстрактного класса быть конструкторы?
Да, в абстрактном классе в Java можно объявить и определить конструкторы. Поскольку создавать экземпляры абстрактных классов нельзя, вызвать такой конструктор можно только при формировании цепочки конструкторов, то есть при создании экземпляра конкретного класса-реализации. Но представьте, что интервьюер задаст затем вопрос: а какой смысл в конструкторе, если создать экземпляр абстрактного класса все равно нельзя? Дело в том, что его всё равно можно использовать для задания начальных значений общих переменных, объявленных в абстрактном классе и используемых различными реализациями. Даже если вы не объявили никакого конструктора, компилятор добавит в абстрактный класс конструктор по умолчанию без аргументов. Без него ваш подкласс не скомпилируется, поскольку первый оператор в любом конструкторе представляет собой неявный вызов super() – конструктора суперкласса по умолчанию в языке Java.
2. Могут ли абстрактные классы в языке Java реализовывать интерфейсы? Должны ли они реализовывать все методы?
Да, абстрактные классы могут реализовывать интерфейсы с помощью ключевого слова implements . Поскольку они абстрактные, то не обязаны реализовывать все методы. Наличие абстрактного базового класса и интерфейса для объявления типа является рекомендуемой практикой. Пример — интерфейс java.util.List и соответствующий абстрактный класс java.util.AbstractList . Поскольку AbstractList реализует все общие методы, то конкретные реализации (например, LinkedList и ArrayList ) не должны реализовать все методы, как в случае, если бы они реализовали интерфейс List напрямую. Это решение сочетает преимущество использования интерфейса для объявления типа и гибкость абстрактного класса для реализации всего общего поведения в одном месте. В книге Джошуа Блоха «Java. Эффективное программирование» есть отличная глава на тему использования интерфейсов и абстрактных классов в Java, для лучшего понимания имеет смысл её изучить.
3. Может ли абстрактный класс быть final?
Нет, не может. Ключевое слово final означает, что класс на вершине иерархии, и у него не может быть наследников. А абстрактный класс без наследников — это сферический конь в вакууме, так как нельзя создать экземпляр abstract class . Таким образом, если класс одновременно abstract и final , то у него нет наследников и нельзя создать его экземпляр. Компилятор Java выдаст ошибку, если сделать класс одновременно abstract и final .
4. Могут ли у абстрактного класса в языке Java быть статические методы?
Да, абстрактные классы могут объявлять и определять статические методы. Только необходимо следовать общим принципам создания статических методов в Java, поскольку они нежелательны при объектно-ориентированном проектировании, ведь переопределение статических методов в Java невозможно. Статические методы в абстрактном классе – явление очень редкое, но, если на это есть уважительные причины, вам ничего не помешает их использовать.
5. Можно ли создать экземпляр абстрактного класса?
Нет, этого делать нельзя. Суть абстрактного класса заключается в том, что он не завершён, и его нужно завершить в классах-наследниках. То есть этот класс не готов к использованию. В нём, например, может отсутствовать реализация каких-то методов. Раз класс не готов к использованию, то нельзя создавать его объект. А вот экземпляры наследников абстрактного класса создавать можно. Компилятор Java выдаст ошибку, если программа попытается создать экземпляр абстрактного класса.
6. Обязательно ли в абстрактном классе должны быть абстрактные методы?
Нет, в абстрактном классе может не быть ни одного абстрактного метода. Сделать класс абстрактным в языке Java можно просто путем использования ключевого слова abstract при объявлении. Компилятор обеспечит выполнение всех структурных ограничений, например, запрета на создание экземпляров этого класса. Кстати, вопрос о том, должны ли быть абстрактные методы в абстрактном классе или интерфейсе – спорный. Мне представляется, что в абстрактном классе должны быть абстрактные методы, поскольку это первое, о чем думает программист, видя абстрактный класс. Это хорошо согласуется с принципом минимизации неожиданностей.
7. Каковы различия между абстрактным классом и интерфейсом в Java?
- Интерфейс описывает только поведение (методы) объекта, а вот состояний (полей) у него нет (кроме public static final ), в то время как у абстрактного класса они могут быть.
- Абстрактный класс наследуется (extends), а интерфейс — реализуется (implements). Мы можем наследовать только один класс, а реализовать интерфейсов — сколько угодно. Интерфейс может наследовать (extends) другой интерфейс/интерфейсы.
- Абстрактные классы используются, когда есть отношение «is-a», то есть класс-наследник расширяет базовый абстрактный класс, а интерфейсы могут быть реализованы разными классами, вовсе не связанными друг с другом.
8. Когда имеет смысл предпочесть абстрактный класс интерфейсу и наоборот?
- Вы хотите поделиться кодом между несколькими тесно связанными классами.
- Вы ожидаете, что классы, которые расширяют ваш абстрактный класс, имеют много общих методов или полей, или требуют других модификаторов доступа, кроме public (например, protected и private ).
- Вы хотите объявить нестатические или не-final поля. Это позволяет вам определять методы, которые могут получить доступ и изменить состояние объекта, которому они принадлежат.
- Вы ожидаете, что несвязанные классы будут реализовывать ваш интерфейс. Например, интерфейсы Comparable и Cloneable реализуются многими несвязанными классами.
- Вы хотите определить поведение конкретного типа данных, но вам не важно, кто его реализует.
- Вы хотите использовать множественное наследование типа.
9. Что такое абстрактный метод в языке Java?
Абстрактный метод – это метод без тела. Вы просто объявляете метод, не определяя его, с использованием ключевого слова abstract в объявлении метода. Все объявленные внутри интерфейса в языке Java методы – по умолчанию абстрактные. Вот пример абстрактного метода в языке Java:
public void abstract printVersion();
Теперь, для реализации этого метода необходимо расширить абстрактный класс и этот метод переопределить.
10. Может ли абстрактный класс в Java содержать метод main ?
Да, абстрактный класс в Java может содержать метод main , ведь это просто еще один статический метод, и абстрактный класс можно выполнять при помощи метода main , если не создавать его экземпляров. Вот и всё, что я хотел рассказать. И помните: абстрактные классы и интерфейсы – ключевые проектные решения в процессе объектно-ориентированного анализа и проектирования, и применять их следует с должной осмотрительностью, конечно, если вы хотите создать гибкую систему.