ООП в Java Flashcards
Какие виды классов есть в java?
Top level class (Обычный класс): -Abstract class (Абстрактный класс); -Final class (Финализированный класс). Interfaces (Интерфейс). Enum (Перечисление). Nested class (Вложенный класс): -Static nested class (Статический вложенный класс); -Member inner class (Простой внутренний класс); -Local inner class (Локальный класс); -Anonymous inner class (Анонимный класс).
Расскажите про вложенные классы. В каких случаях они применяются?
Класс называется вложенным (nested), если он определен внутри другого класса.
Вложенный класс создается для того, чтобы обслуживать окружающий его класс.
Это пример композиции. Внутренний класс это часть целого класса.
Вложенные классы - по сути, это более подробное описание каких-то деталей нашего внешнего класса.
Если класс полезен только для одного другого класса, то вполне логично встроить его в этот класс и хранить их вместе.
Использование вложенных классов увеличивает инкапсуляцию.
Вложенные классы применяются в тех случаях, когда нужно написать небольшой вспомогательный код для другого класса.
Вложенный класс создают также, чтобы скрыть его переменные и методы от внешнего мира.
Внутренние классы также есть смысл использовать, если предполагается, что они будут использовать элементы родителя, чтобы не передавать лишнего в конструкторах.
Особенности нестатических вложенных классов Java:
- Они существуют только у объектов, потому для их создания нужен объект.
- Внутри Java класса не может быть статических переменных. Если вам нужны какие-то константы или что-либо еще статическое, выносить их нужно во внешний класс. Это связано с тесной связью нестатического вложенного класса с внешним классом.
- У класса полный доступ ко всем приватным полям внешнего класса. Данная особенность работает в две стороны.
- Можно получить ссылку на экземпляр внешнего класса.
Статические классы внутри внешнего класса:
Данный вид классов не отличается ничем от обычного внешнего класса, кроме одного: для создания экземпляра такого класса, нужно через точку перечислить весь путь от внешнего класса до нужного.
Статические классы используются для того, чтобы укомплектовать связанные классы рядом, чтобы с логической структурой было работать проще.
Количество классов уменьшилось.
Все классы внутри их класса-родителя.
https://javarush.ru/groups/posts/2181-vlozhennihe-vnutrennie-klassih
Что такое «локальный класс»? Каковы его особенности?
Данные классы объявляются внутри других методов. По сути, они обладают всеми свойствами нестатического вложенного класса, только создавать их экземпляры можно только в методе, при чем метод не может быть статическим (для их создания нужен экземпляр внешнего класса, в нестатические методы неявно передается ссылка на экземпляр вызывающего объекта, а в статическом методе данной ссылки нет).
- Локальные классы способны работать только с final переменными метода. Все дело в том, что экземпляры локальных классов способны сохраняться в «куче» после завершения работы метода, а переменная может быть стёрта. Если же переменная объявлена final, то компилятор может сохранить копию переменной для дальнейшего использования объектом. И еще: с 8+ версий Java можно использовать не final переменные в локальных классах, но только при условии, что они не будут изменяться.
- Локальные классы нельзя объявлять с модификаторами доступа.
- Локальные классы обладают доступом к переменным метода.
Локальные классы можно встретить крайне редко, так как они затрудняют прочтение кода и не обладают никакими плюсами, кроме одного – доступ к переменным метода.
https://javarush.ru/groups/posts/2190-vnutrennie-klassih-v-lokaljhnom-metode
Что такое «анонимные классы»? Где они применяются?
Анонимные классы – просто обычные нестатические вложенные классы. Их особенность в удобстве их использования. Можно написать свой класс прямо при создании экземпляра другого класса.
Мы просто совмещаем в одном месте две вещи: создание экземпляра одного класса и создание экземпляра его внутреннего-класса наследника. Иначе нам нужно создавать класс отдельно и использовать более длинные конструкции, чтобы добиться того же самого результата.
Использование анонимных классов оправдано во многих случаях, в частности когда:
- тело класса является очень коротким;
- нужен только один экземпляр класса;
- класс используется в месте его создания или сразу после него;
- имя класса не важно и не облегчает понимание кода.
Часто анонимные классы используются в графических интерфейсах для создания обработчиков событий. Например для создания кнопки и реакции на её нажатие.
https://javarush.ru/groups/posts/2193-anonimnihe-klassih
Каким образом из вложенного класса получить доступ к полю внешнего
класса?
РодительскийКласс.this.Поле
Внутренний класс в локальном методе не может использовать локальные переменные внешнего метода до тех пор, пока локальная переменная не будет объявлена как финальная (final).
Что такое перечисления (enum)?
При задаче необходимости ограничения множества допустимых значений для некоторого типа данных в Java предусмотрен специальный тип данных – перечисление (enum)
Перечисление — это класс. Объявляя enum мы неявно создаем класс производный от java.lang.Enum
Элементы перечисления — экземпляры enum-класса, доступные статически
Их статическая доступность позволяет нам выполнять сравнение с помощью оператора сравнения ссылок (==)
По сравнению с обычными классами, на Enum наложили одно серьезное ограничение — от него невозможно наследоваться.
Кроме того, у перечислений есть характерные только для них методы:
values(): возвращает массив из всех хранящихся в Enum значений:
ordinal(): возвращает порядковый номер константы. Отсчет начинается с нуля:
valueOf(): возвращает объект Enum, соответствующий переданному имени:
Обрати внимание: мы указываем названия элементов Enum прописными буквами, поскольку это константы, а для них предусмотрена именно такая запись, а не camelCase.
Как проблема ромбовидного наследования решена в java?
в Java запрещено множественное наследование от классов. Java не поддерживает множественное наследование классов потому, что это может привести к ромбовидной проблеме.
В Java множественное наследование не поддерживается в классах, но оно поддерживается в интерфейсах. И один интерфейс может расширять множество других интерфейсов. Интерфейсы только объявляют методы, а реализация будет выполнена в классах, наследующих интерфейс.
Что такое конструктор по умолчанию?
Конструктор по умолчанию – это конструктор класса, который объявляется без параметров. Если класс не содержит явным образом определенный конструктор, тогда при создании объекта автоматически вызывается конструктор по умолчанию.
Этот конструктор пустой и не делает ничего, кроме вызова конструктора суперкласса.
Если в классе определен конструктор с параметрами, а перегруженного конструктора без параметров нет, то вызов конструктора без параметров является ошибкой.
Могут ли быть приватные конструкторы? Для чего они нужны?
Можно сделать конструктор приватным, чтобы не дать внешнему коду создать новый экземпляр класса.
В шаблоне проектирования, называемом Singleton, приватный конструктор используется, чтобы гарантировать, что всегда существует только один экземпляр класса. Класс Singleton предоставляет статический метод для получения этого уникального экземпляра.
Другое - это делегирование конструкторов; у вас может быть один конструктор, который принимает множество различных параметров, которые действительно являются деталями реализации, поэтому вы делаете их закрытыми. Но затем ваши остальные конструкторы делегируют ему.
Расскажите про классы-загрузчики и про динамическую загрузку классов.
Используется для поставки в JVM скомпилированного байт-кода, который, как правило, хранится в файлах с расширением .class, но может быть также получен из других источников, например, загружен по сети или же сгенерирован самим приложением.
Для того, чтобы получить загрузчик, которым был загружен класс А, необходимо воспользоваться методом A.class.getClassLoader().
Классы загружаются по мере надобности, за небольшим исключением. Некоторые базовые классы (java.lang.* в частности) загружаются при старте приложения. Классы расширений ($JAVA_HOME/lib/ext), пользовательские и большинство системных классов загружаются по мере их использования.
Различают 3-и вида загрузчиков в Java. Это — базовый загрузчик (bootstrap), системный загрузчик (System Classloader), загрузчик расширений (Extension Classloader).
- Bootstrap — реализован на уровне JVM и не имеет обратной связи со средой исполнения. Данным загрузчиком загружаются классы из директории $JAVA_HOME/lib. Т.е. всеми любимый rt.jar загружается именно базовым загрузчиком.
- System Classloader — системный загрузчик, реализованный уже на уровне JRE. Этим загрузчиком загружаются классы, пути к которым указаны в переменной окружения CLASSPATH.
- Extension Classloader — загрузчик расширений. Данный загрузчик загружает классы из директории $JAVA_HOME/lib/ext.
Различают текущий загрузчик (Current Classloader) и загрузчик контекста (Context Classloader). - Current Classloader — это загрузчик класса, код которого в данный момент исполняется. Текущий загрузчик используется по умолчанию для загрузки классов в процессе исполнения. При любой декларации класса, ранее не загруженного.
- Context Classloader — загрузчик контекста текущего потока. Загрузчик контекста устанавливается автоматически для каждого нового потока. При этом, используется загрузчик родительского потока.
Загрузчики классов образуют иерархию. Корневым является базовый (у него предка нет). Все остальные загрузчики при инициализации инстанциируют ссылку на родительский загрузчик. Такая иерархия необходима для модели делегирования загрузки.
https://javarush.ru/groups/posts/646-kak-proiskhodit-zagruzka-klassov-v-jvm
Чем отличаются конструкторы по-умолчанию, конструктор копирования и
конструктор с параметрами?
Конструктор по умолчанию не принимает никаких параметров.
Конструктор копирования принимает в качестве параметра объект класса. Конструктор с параметрами принимает на вход параметры (обычно необходимые для инициализации полей класса).
Какие модификаторы доступа есть в Java? Какие применимы к классам?
- private (закрытый) – доступ к члену класса не предоставляется никому, кроме методов этого класса. Другие классы того же пакета также не могут обращаться к private-членам.
- default - доступ по умолчанию, когда никакой модификатор не присутствует – член класса считается открытым внутри своего собственного пакета, но не доступен для кода, расположенного вне этого пакета.
- protected (защищённый) – доступ в пределах пакета и классов наследников. Доступ в классе из другого пакета будет к методам public и protected главного класса.
- public (открытый) – доступ для всех из любого другого кода проекта
Модификаторы в списке расположены по возрастающей видимости в программе.
Что означает модификатор static?
Модификатор static в Java напрямую связан с классом. Если поле статично, значит оно принадлежит классу, если метод статичный — аналогично: он принадлежит классу. Исходя из этого, можно обращаться к статическому методу или полю, используя имя класса.
Может ли статический метод быть переопределён или перегружен?
Перегружен - да. Всё работает точно так же как и с обычными методами - 2 статических метода могут иметь одинаковое имя, если количество их параметров или типов различается.
Переопределен - нет. Выбор вызываемого статического метода происходит при раннем связывании (на этапе компиляции, а не выполнения) и выполняться всегда будет родительский метод, хотя синтаксически переопределение статического метода это вполне корректная языковая конструкция.
В целом, к статическим полям и методам рекомендуется обращаться через имя класса, а не объект.
Могут ли нестатические методы перегрузить статические?
Да. В итоге получится два разных метода. Статический будет принадлежать классу и будет доступен через его имя, а нестатический будет принадлежать конкретному объекту и доступен через вызов метода этого объекта.
Можно ли сузить уровень доступа/тип возвращаемого значения при
переопределении метода?
Изменить можно, но при условии его расширения (package private -> protected -> public)
Нет смысла делать функцию в наследнике менее открытой, потому что она всё равно может быть вызвана через базовый класс.
Принцип подстановки Лисков. Там, где допустимо использовать тип Х, должно быть допустимо использовать и любой тип, наследующийся от него.
Как получить доступ к переопределенным методам родительского класса?
С помощью ключевого слова super мы можем обратиться к любому члену родительского класса - методу или полю, если они не определены с модификатором private.
super.method();
Тип возвращаемого значения метода при перегрузке и
переопределении + модификаторы доступа.
Возможно ли при переопределении метода изменить: модификатор доступа, возвращаемый тип, тип аргумента или их количество, имена аргументов или их порядок; убирать, добавлять, изменять порядок следования элементов секции throws?
При переопределении метода сужать модификатор доступа не разрешается, т.к. это приведет к нарушению принципа подстановки Барбары Лисков. Расширение уровня доступа возможно.
Можно изменять все, что не мешает компилятору понять какой метод родительского класса имеется в виду:
Изменять тип возвращаемого значения при переопределении метода разрешено только в сторону сужения типа (вместо родительского класса - наследника).
При изменении типа, количества, порядка следования аргументов вместо переопределения будет происходить overloading (перегрузка) метода.
Секцию throws метода можно не указывать, но стоит помнить, что она остаётся действительной, если уже определена у метода родительского класса. Также, возможно добавлять новые исключения, являющиеся наследниками от уже объявленных или исключения RuntimeException. Порядок следования таких элементов при переопределении значения не имеет.
Что можно изменить в сигнатуре метода при переопределении? Можно ли
менять модификаторы (throws и тп)?
(override) В новом методе должны быть те же сигнатура и тип возвращаемого результата, что и у метода родительского класса. Сигнатура метода включает название метода и типы параметров в определенном порядке. Имя плюс типы параметров (упорядоченные). Возвращаемое значение не входит в сигнатуру, а порядок следования параметров – входит.
Переопределяться могут только наследованные методы, т.е. полиморфизм применим только к переопределению.
Могут ли классы быть статическими?
Статическим классом в java может быть только вложенный класс - есть вложенные(static) и внутрение классы.
Объекты которых можно создавать, не создавая инстанса класса в котором он лежит.
Статический класс не имеет ссылки не внешний,
static имеет доступ только к статичным полям.
Но можно имитировать статический класс (через final private static).
О чем говорит ключевое слово final?
Модификатор final может применяться к переменным, параметрам методов, полям и методам класса или самим классам.
● Класс не может иметь наследников; Это полезно при создании immutable (неизменяемых) объектов, например, класс String объявлен, как final.
● Метод не может быть переопределен в классах наследниках;
● Поле не может изменить свое значение после инициализации;
● Параметры методов не могут изменять своё значение внутри метода;
● Локальные переменные не могут быть изменены после присвоения им
значения.
Для ссылочных переменных это означает, что после присвоения объекта, нельзя изменить ссылку на данный объект. Это важно! Ссылку изменить нельзя, но состояние объекта изменять можно.
Где и для чего используется модификатор abstract?
Класс помеченный модификатором abstract называется абстрактным классом. Такие классы могут выступать только предками для других классов. Создавать экземпляры самого абстрактного класса не разрешается. При этом наследниками абстрактного класса могут быть как другие абстрактные классы, так и классы, допускающие создание объектов.
Метод помеченный ключевым словом abstract - абстрактный метод, т.е. метод, который не имеет реализации. Если в классе присутствует хотя бы один абстрактный метод, то весь класс должен быть объявлен абстрактным.
Использование абстрактных классов и методов позволяет описать некий шаблон объекта, который должен быть реализован в других классах. В них же самих описывается лишь некое общее для всех потомков поведение.
НА ЗАМЕТКУ!!!
Особенности абстрактных классов:
1) Может быть конструктор (для вызовов по цепочке из наследников)
2) Имплементят интерфейсы, но не обязаны реализовывать их методы
3) Не могут быть final
4) Могут содержать static методы
5) Нельзя создать объект
6) Абстрактные методы могут отсутствовать
7) Может содержать метод main()
Может ли быть абстрактный класс без абстрактных методов?
Да, может. Абстрактный класс может содержать как обычные, так и абстрактные методы.
Может ли обычный класс иметь абстрактный метод? Ответ: не может. Абстрактный класс может иметь абстрактный и обычный метод, но обычный класс не может иметь абстрактный метод.
Могут ли быть конструкторы у абстрактных классов? Для чего они нужны?
Да, в абстрактном классе в Java можно объявить и определить конструкторы. Поскольку создавать экземпляры абстрактных классов нельзя, вызвать такой конструктор можно только при формировании цепочки конструкторов, то есть при создании экземпляра конкретного класса-реализации.
Конструктор можно использовать для задания начальных значений общих переменных, объявленных в абстрактном классе и используемых различными реализациями.
Даже если вы не объявили никакого конструктора, компилятор добавит в абстрактный класс конструктор по умолчанию без аргументов.
Абстрактные классы могут реализовывать интерфейсы с помощью ключевого слова implements. Поскольку они абстрактные, то не обязаны реализовывать все методы.