JavaRush /Java блог /Random /Разбор вопросов и ответов с собеседований на Java-разрабо...
Константин
36 уровень

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3

Статья из группы Random
Привет! Как невозможно научиться управлять самолетом без специального обучения, так и невозможно стать Java-разработчиком, не потратив долгие часы на изучение необходимой теоретической базы. Сегодня мы поработаем именно над этим: продолжим разбор 250+ вопросов на собеседованиях для Java-разработчиков и, соответственно, ответов на них. Здесь — первая и вторая часть разбора. Да несомненно, можно стать хорошим Java-разработчиком и без всех этих вопросов. Тем не менее, если вы хорошо разберётесь во всех тонкостях языка Java, это даст вам преимущество, сделав более желанным кандидатом в глазах вашего будущего работодателя.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3 - 1

20. Какие элементы языка отвечают за инкапсуляцию?

Как мы помним, инкапсуляция — это сокрытие деталей реализации класса. То есть, когда наш класс используется извне, внутренняя начинка и логика не очевидны. И какие же элементы языка отвечают за это? Естественно, модификаторы доступа! То, что нам необходимо скрыть, мы отмечаем модификатором private. Например, приватные поля класса или какие-нибудь внутренние методы, помогающие реализовать некий внутренний функционал. А к тому, к чему мы хотим предоставить внешний доступ, добавляем модификатор доступа public. Например, метод, отвечающий за предоставление какой-то функциональности (внутри которого может использоваться множество приватных методов) или те же геттеры и сеттеры для доступа к приватным полям класса. Ах, да у нас еще есть модификаторы default и protected, которые можно использовать для более гибкой и специфической настройки доступов к избранным частям класса.

21. Какие элементы языка отвечают за наследование?

Наследование — это механизм, который позволяет создавать классы на основе другого класса. В Java для этих целей используют ключевое слово extends. Например, у нас есть некий класс Cat, и мы хотим создать его наследника — Lion. В коде это будет выглядеть как-то так:

public class Lion extends Cat
И это значит, что класс Lion наследует все методы и переменные класса Cat, кроме статических. Также к элементам языка, отвечающим за наследование, можно отнести super. Это ссылка, аналогичная this, но если this ссылается на объект, в котором ее вызвали, то super ссылается на текущий объект родителя. Как правило super используется:
  1. Для вызова конструктора суперкласса: например, у класса Cat есть внутренняя переменная name, которую нужно проинициализировать в конструкторе. В конструкторе класса Lion это будет выглядеть так:

    
    public Lion(final String name) {
       super(name);
    }
    
  2. Для обращения к полям и методам родителя: например, в классе Cat у нас есть проинициализированное поле age:

    
    public class Cat {
       int age = 10;
    
В то же время у нас есть такое же проинициализированное поле в Lion:

public class Lion extends Cat {
   int age = 15;
И если мы хотим обратиться из объекта Lion к переменной age родительского объекта, это нужно делать через super:

super.name

22. Какие элементы языка отвечают за полиморфизм?

Полиморфизм — это способность объекта одной сигнатуры принимать множество форм (множество реализаций).Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3 - 2Можно смело сказать, что в Java за полиморфизм отвечают ключевые слова implements и extends. implements — когда мы создаем наш интерфейс, мы реализуем в каком-то классе одну из его возможных форм, но ведь она не единственная форма, не так ли? Вспомним, как выглядит применение implements:

public class Cat implements Animal
И в Cat классе мы должны реализовать все абстрактные методы, представленные в интерфейсе Animal. Так же и наследование: в классе-наследнике мы можем переопределить уже существующую реализацию метода. Например: несколько наследников -> несколько различных переопределений одного и того же метода. Ну либо суперкласс был абстрактным и у него есть некий метод, который нужно реализовывать по-особому для каждого его наследника. То есть, можно сказать, что метод будет принимать множество форм. Также в этом нам может помочь аннотация @Override, которая ставится над реализуемыми методами и обозначает, что мы хотим реализовать или переопределить (если реализация уже существует в суперклассе) тот или иной метод суперкласса или интерфейса. Она не обязательна и используется для более легкого обнаружения ошибок. Этой аннотацией вы показываете компилятору, что хотите переопределить/имплементировать метод суперкласса/интерфейса, и он будет следить, чтобы вы не сделали ошибок в сигнатуре метода.

23. Что такое SOLID? Приведите примеры

SOLID — акроним из названий пяти основных принципов дизайна для ООП, придуманных Робертом Мартином. S — Single-responsibility principle — принцип единой ответственности, который гласит, что у класса должна быть только одна цель и единственное назначение. То есть, не стоит создавать классы, которые делают все. В этом случае можно воспроизвести антипаттерн “Божественный объект”. Если у вас есть объект Cat, в нем должны находиться методы, взаимодействующие только с его внутренней функциональностью, но никак не бизнес-логика, которая не имеет отношения к этому инстансу. Например, какое-нибудь сохранение объектов данного типа куда-либо. Этот внешний функционал (относительно Cat), нужно выносить в другие классы, какие-нибудь сервисы, задача которых — обеспечить бизнес-логику для объектов данного типа. O — Open-closed principle — принцип открытости/закрытости. Он означает, что программные сущности (классы, интерфейсы) должны быть открыты для расширения, но закрыты для модификации. Например, нам понадобился функционал, схожий с функционалом уже существующего класса Cat, но немного другой. Вместо того, чтобы изменять функционал класса Cat, при этом ломая те места, в которых он уже задействован, мы используем наследование или композицию. Как итог — мы добились своей цели с модифицированным функционалом класса Cat, но при этом мы не изменили его и ничего не сломали. L — Liskov substitution principle — принцип подстановки Барбары Лисков. Принцип гласит, что функция, использующая базовый тип, должна иметь возможность использовать подтипы базового типа, не зная об этом. Например, наш класс Cat должен быть заменяемым любым его наследником, скажем, Lion, без кардинального изменения поведения. Общая логика (поведение) остается такой же, но меняются детали самой реализации того или иного функционала. I — Interface segregation principle — принцип разделения интерфейса. Данный принцип гласит, что лучше иметь множество специализированных (узконаправленных) интерфейсов, чем один универсальный. Например, пользователь реализует некоторый интерфейс, из которого ему нужен лишь он метод, но при этом у данного интерфейса есть еще девять методов, которые никак не относятся к логике нужного метода. В таком случае пользователю нужно будет реализовать десять методов интерфейса, девять из которых лишние для него! Вместо этого лучше сделать десять различных интерфейсов которые можно реализовать при необходимости. Ну или не десять, а несколько, у которых будут методы, тесно связанные единой целью интерфейса. D — Dependency Inversion Principle — принцип инверсии зависимостей. Принцип говорит о том, что модули верхних уровней не должны зависеть от модулей нижних уровней. Ещё этот принцип описывают как “абстракция не должна зависеть от деталей, детали должны зависеть от абстракции”. То есть, мы должны строить нашу логику, ссылаясь на интерфейсы, и уже потом в этот функционал передавать конкретные объекты, классы которых и реализуют необходимый интерфейс. Например, если у нас есть интерфейс Cat и некоторые его реализации, скажем, Lion и HomeCat, мы строим нашу логику взаимодействия именно с типом интерфейса Cat, и уже потом подставляем конкретную реализацию Lion или HomeCat, но никак не наоборот.

24. Что такое класс, объект, интерфейс?

Как мы помним, Java — это ООП язык. То есть, программы на Java построены на взаимодействии между объектами. Получается, программа — это такой себе муравейник, где каждый муравей это — объект.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3 - 3Объекты — это некоторые сгруппированные данные, в которых содержатся различные методы (функции) для взаимодействия с этими внутренними данными. А классы — это инструкции, шаблоны для создания объектов. То есть, может быть множество объектов, построенных по одной и той же инструкции, наполненных разными или одинаковыми значениями данных. Если приводить пример из жизни, можно сказать, что класс — это чертеж здания, а объект — конкретно созданное здание по этому чертежу. Интерфейсы — это аналоги классов с той разницей, что по ним нельзя создать объекты. Их цель — добавить элемент абстракции в Java. Точнее, добавить гибкость во взаимоотношениях классов и объектов. Под гибкостью имеем в виду описанные ранее полиморфизм и абстракцию, которые в свою очередь открывают множество возможностей для построения внутренней архитектуры приложения.

25. Что такое класс POJO? Приведите пример такого класса

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3 - 4POJO — Plain Old Java Object — старый добрый Java-объект: простой объект, класса, который не унаследован от какого-то специфического класса и не реализует никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели. Другими словами POJO класс — это просто класс без особых требований. Единственное требование — отсутствие различных наворотов, завязанных на определенном фреймворке. Как правило такие классы не наследуют от других классов (кроме классов POJO из того же пакета), не реализуют интерфейсов — иногда делается исключение для маркерных интерфейсов из стандартной библиотеки типа Serializable или Cloneable — не используют аннотаций и не зависят от сторонних библиотек. Но отмечу, что у POJO могут быть и методы с бизнес-логикой, и произвольного вида конструкторы. Если разрешить аннотации, не вносящие изменения в семантику класса (без которых назначение объекта и логика его работы не изменятся), к POJO также можно отнести Entity сущности JPA и объекты DTO, десериализуемые из XML или JSON, правила для которых заданы в аннотациях. Также для POJO классов желательно переопределить equals и hashCode, ведь это может помочь им лучше выполнять свою роль. Пример POJO класса:

public class User {
   private Long id;
   private String firstName;
   private String lastName;
   private Long age;
 
   public User(final Long id, final String firstName, final String lastName, final long age) {
       this.id = id;
       this.firstName = firstName;
       this.lastName = lastName;
       this.age = age;
   }
 
   public Long getId() {
       return this.id;
   }
 
   public String getFirstName() {
       return this.firstName;
   }
 
   public String getLastName() {
       return this.lastName;
   }
 
   public Long getAge() {
       return this.age;
   }
 
   @Override
   public boolean equals(final Object o) {
       if (this == o) return true;
       if (o == null || this.getClass() != o.getClass()) return false;
       final User user = (User) o;
       return Objects.equals(this.id, user.id) &&
               Objects.equals(this.firstName, user.firstName) &&
               Objects.equals(this.lastName, user.lastName) &&
               Objects.equals(this.age, user.age);
   }
 
   @Override
   public int hashCode() {
       return Objects.hash(this.id, this.firstName, this.lastName, this.age);
   }
}

26. Какие элементы может содержать класс?

Класс может содержать такие элементы:
  • поля класса;
  • статические поля класса;
  • блок инициализации;
  • статический блок инициализации;
  • конструкторы (пустой всегда определен по умолчанию);
  • методы;
  • статические методы;
  • различные аннотации (которые могут висеть над самим классом или его составляющими);
  • дженерики;
  • наследования от других классов (extends) или имплементации от интерфейсов (implements).

27. Расскажите о наследовании в Java. Каковы особенности использования ключевого слова super?

Выше я уже рассказал о наследовании и ключевом слове super в Java. Упомяну еще несколько важных моментов:
  1. Возможно наследование лишь одного класса: множественное наследование в Java отсутствует (но с появлением дефолтных методов в Java 8 это утверждение станет весьма спорным).
  2. Приватные методы и поля наследуются тоже, просто к ним не будет доступа с наследника (но если у нас, к примеру, приватное поле и к нему есть public или protected — геттеры и сеттеры, с полем можно работать через них).
  3. final классы не наследуются.
  4. final методы не переопределяются (но их можно наследовать и перегружать).
  5. static методы и переменные не наследуются (т. к. они привязаны не к объектам, а к классам).
  6. При наследовании от абстрактных классов, обязательна реализация их абстрактных методов, либо текущий класс тоже нужно объявить абстрактным.
  7. При наличии не дефолтных конструкторов в родителе, в классе потомке их обязательно нужно переопределять (но @Override над ними не пишется).
  8. Переопределенным методам в наследнике можно расширять модификатор доступа: private -> default -> protected -> public.
  9. Переопределенным методам в наследнике можно сужать прописываемые исключения, например: Exception -> IOException -> FileNotFoundException.
Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3 - 5

28. Что такое сигнатура метода? Приведите примеры правильных и неправильных сигнатур

Сигнатура метода — это имя метода плюс типы входящих параметров (причем порядок параметров имеет значение). В сигнатуру метода не входит возвращаемое значение, а также бросаемые им исключения. Пример правильной сигнатуры:

doSomething(int, double, double)
Пример неправильной сигнатуры:

void doSomething(int firstArg, int secondArg) throws Exception
Сигнатура метода в сочетании с типом возвращаемого значения и перечнем бросаемых исключений называется контрактом метода. На сегодня это все. See you later!Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3 - 6
Другие материалы серии:
Комментарии (13)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Olga Уровень 35
3 июля 2023
Примеры для правильной и неправильной сигнатуры метода перепутаны
Anastasiya Уровень 30
17 января 2023
27. static методы и переменные не наследуются (т. к. они привязаны не к объектам, а к классам) - неверно. Из Oracle "A subclass inherits all of the public and protected members of its parent, no matter what package the subclass is in.". Т.е. статич методы и переменные наследуются, но не могут быть переопределены
27 марта 2021
27 марта 2021
ну помойм рошчотам ти публика учоних по ага по програмируваня удачи нуй потактече пока
27 марта 2021
я незнаю что то знакомає нешлишал о таком за весі 1час нуйну ахахахахахах ну бачив таке в морском патруле
Илья Уровень 30
24 марта 2021
Круто! Спасибо, в этот раз (в отличие от первой части) я ответил на все вопросы самостоятельно. Ну почти на все - про POJO не знал). Так рад за себя)
hidden #2322530 Уровень 41
23 марта 2021
конструкторы (пустой всегда определен по умолчанию); если в класс добавлен хотя бы один конструктор с аргументами. то пустой конструктор надо добавлять вручную. он не будет добавлен по умолчанию. для чего это надо? например для сериализации или работы с ORM Сигнатура метода в сочетании с типом возвращаемого значения и перечнем бросаемых исключений называется контрактом метода. еще по другому "заголовок метода" Переопределенным методам в наследнике можно расширять модификатор доступа: private -> default -> protected -> public. приватные методы не наследуются. поэтому этот модификатор расширить не получится.