Junior Java Developer. Подготовка к собеседованию

в 11:45, , рубрики: Без рубрики

Вступление

Здравствуйте, уважаемы читатели. На написание этой статьи меня сподвиг мой товарищ, который в настоящий момент готовится к собеседованию. Сразу скажу, в интернете есть довольно много списков вопросов, которые задают на собеседовании. Но моей целью было собрать именно те вопросы, которые задаются чаще всего и именно на эту позицию.

Почти все из нас(не берем во внимание людей, которые захотели работать самостоятельно, а не на «дядю») рано или поздно понимали, что пришло время идти на первое в своей жизни собеседование. Кто то был уверен в своих силах, так как имел уже опыт разработки серьезных и не очень проектов за плечами. Но в большинстве своем первое собеседование для людей — это во многом неизвесность.

Обычно, вся информация об этом важном мероприятии представляет из себя рассказы товарищей, которые уже работают(ну или не работают). Если перефразировать моего преподавателя по программированию в университете, то «Собеседование — это как лотерея». Это я к тому, что собеседование представляет из себя общение людей, а не человека с роботом. Поэтому можно обладать не очень большим количеством знаний и опыта, но у собеседующего именно сегодня родился сын(дочь) и шансы попасть в компанию выше, чем если бы настроение было плохое.

Но, психологические аспекты подготовки к собеседованию я обсуждать в статье не буду, так как на хабре достаточно статей по этой теме. А обсудим лучше техническую сторону.

Сразу скажу, я опишу с разъяснениями только те вопросы, которые чаще всего спрашивают на собеседованиях на позицию Java Junior Developer. Т.е. обычно от Вас требуют начальных знаний, ничего сверхъестественного. Но, как показывает практика, новички путаются в многогранном мире Java и обилии инструментов, с ним связанных. Я постараюсь облегчить им восхождение на первую ступень.

Наследование

Наследование в Java реализовано с помощью ключевого слова extends. Но в Java Вы можете в качестве родителя указать только один класс. Это очень важная особенность, про которую любят спрашивать. Так что запомните, что множественного наследования в Java нет! Для примера — такой код не скомпилируется:

public class Car extends AbstractCar, OtherAbstractCar {

}

Возникает вопрос, а как же использовать в качестве родителей несколько классов? Ответ — через интерфейсы(о них ниже) с помощью ключевого слова implements.

Следующий код показывает на примере, как это использовать:

public class Car implements AbstractCar, OtherAbstractCar {

}

Если же Вы захотите совместить эти два подхода, то нужно учитывать, что сначала пишется extends, а только потом implements:
public class Car extends ParentCar implements AbstractCar, OtherAbstractCar {}

Создание экземпляра объекта

Важно понимать различие между классом и объектом. Объект — это экземпляр класса. Объекты в Java создаются с помощью ключевого слова new:

public abstract class AbstractCar {

    public static void main(String[] str) {
         Object obj = new Object();
    }

}

Классы, абстрактные классы, интерфейсы

Класс — это совокупность свойств и методов некоего объекта, который Вы хотите описать. Для примера можно взять класс Car:

public class Car {

    private int cost;
    private String model;

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public int getCost() {
        return cost;
    }

    public void setCost(int cost) {
        this.cost = cost;
    }
    
    public String getDescription() {
        return model + cost;       
    }
    
}

У данного класса есть свойства model, cost, а также метод, позволяющий получить краткое описание машины — getDesription. Также прошу запомнить, что имя класса должно совпадать с именем файла, в котором он объявлен, за исключением расширения. Также нужно учесть, что в одном файле может быть объявлен только один public класс.

Абстрактный класс — это класс, который может содержать абстрактные методы. Т.е. методы, помеченные модификатором abstract. Такие методы не имеют реализации в классе, в котором объявлены. Реализация осуществляется в классах наследниках. Причем в абстрактном классе могут содержаться и конкретные методы и при этом не быть совсем абстрактных. Сразу пример. Есть тот же класс Car и его наследник — класс Fiat.

public abstract class AbstractCar {

    public abstract String getDescription();

    public String getPrice() {
        return "100";
    }

}

public class Fiat extends AbstractCar {

    public String getDescription() {
        return "Fiat";
    }

}

Как мы видим, конкретный класс Fiat переопределил метод своего getDescription родителя.

Интерфейс — это абстрактный класс, который представляет «контракт» между ним и использующим его классом. Т.е. абсолютно все методы, которые есть в интерфейсе должны быть реализованы в классах, которые используют его. Также стоит понимать, что в интерфейсе не может быть реализаций ни одного метода. По сути — все методы в нем абстрактны, просто для них не нужно указывать ключевое слово abstract. Также отсюда вытекает то, что методы могут иметь только два модификатора доступа — public и package и никаких больше(про модификаторы ниже).

Пакеты

Пакет(package) — это аналог пространства имен. Он необходим для того, чтобы обеспечивать уникальность имен. Для примера. У нас в проекте есть 2 класса, обеспечивающие вывод различных экранов. Причем классы называются одинаково, что то вроде TestScreen. Понятно, что компилятор будет ругаться, т.к. на лицо неопределенность. Здесь то в дело и вступают пакеты. Если создать 2 разных пакета с разными именами и поместить классы в них, то ошибок компиляции не будет. Нужно также понимать, что существует полное имя класса, которое получается путем объединения имени пакеты и имени класса. Если класс в пакете com.home, то его полное имя будет com.home.TestScreen. На диске пакеты представляют собой обычные папки, вложенные друг в друга. Т.е. наш пакет будет представлять собой папку com с вложенной в нее папкойhome.

Модификаторы доступа

Модификаторы доступа нужны для того, чтобы ограничить область видимости класса, метода или поля. Существуют 4 модификатора:

package — модификатор по умолчанию. Если не указывать ничего, то у метода(класса, поля) будет именно такой модификатор. Позволяет получать доступ из любого класса в текущем пакете.

public — модификатор, который позволяет получить доступ откуда угодно(из другого пакета, класса).

protected — модификатор, который позволяет получить доступ только из классов
наследников и внутри самого класса.

private — модификатор, который позволяет получить доступ только внутри класса.

Хешкод, зачем он нужен(опционально — про equals)

Этот вопрос — тоже частый гость на собеседованиях. Ответ прост — это положительное целое число, которое формируется для объекта по какому то правилу. Обычно следующим идет вопрос — А где и для чего он используется?. Ответ тоже прост — он используется в коллекциях, основанных на hash-кодах(Hashset, HashMap), для группировки объектов по хеш-ключу и доступа. По поводу equals обычно спрашивают, нужно ли переопределять hashcode, если переопределяешь equals — ответ «Да, всегда». Подробный ответ ниже — в разделе Коллекции.

Коллекции

Всегда спрашивают про коллекции, их отличия и особенности. Я опишу только основные.

List — представляет упорядоченную коллекцию, которая позволяет хранить одинаковые элементы и которая позволяет обратиться к элементу по его позиции.

Реализации:

ArrayList — обеспечивает лучшее по сравнению с LinkedList время выполнения операций поиска. Не синхронизирован.
Vector — аналог ArrayList, с тем отличием, что все методы у него синхронизированы, соответственно — он медленнее работает, но потокобезопасен.
LinkedList — двунаправленный список. обеспечивает лучшее по сравнению с ArrayList время выполнения операций вставки/удаления, тк каждый элемент

содержит в себе ссылки на предыдущий элемент(или null, если это первый элемент в списке) и на следующий элемент(или null, если это последний элемент в списке). Также позволяет удалять первый и последний элементы.

Set — представляет коллекцию, которая не позволяет хранить одинаковые элементы.

Реализации:

HashSet — не упорядоченная коллекция, которая не сортируется. Обеспечивает лучшую, по сравнению с TreeSet производительность операций вставки/удаления.
TreeSet — упорядоченная коллекция. Обеспечивает лучшую, по сравнению с HashSet производительность операций поиска.

Map — представляет коллекцию, которая хранит пары «ключ-значение».

Реализации:

HashMap — допускает много пустых значений и только один пустой ключе, не
упорядочивается. Не синхронизирован.
HashTable — основное отличие от HasnMap в том, что все его методы синхронизированы. Также в нем не допускаются пустые ключи и значения.
TreeMap — упорядоченная коллекция.

Теперь перейдем к описанию того, о чем я говорил в прошлом пункте, а именно — каким образом некоторые коллекции используют хешкод объекта. Все очень просто. Каждая коллекция, использующая хешкоды, представляет собой массив, каждый элемент которого содержит цепочку пар «ключ-значение», которые Вы туда помещаете. Причем индексами элементов массива являются результаты вычисления функции indexFor(hash, collLength), которая и определяет позицию Вашей пары в массиве на основе хешкода ключа. Причем нужно отметить, что в функцию передается не исходный хешкод ключа, а значение, которое было получено на его основе с помощью статического метода hash(keyHashCode)

При этом не исключено, что хеш коды разных объектов могут совпасть. Такая ситуация называется коллизией. Когда происходит коллизия, то одним из решений является использования метода цепочек. Т.е. в конец связанного списка, на который ссылается элемент массива, просто добавляется ваша пара значений. Возникает вопрос — а как же тогда получить именно ту пару, которую хочешь, если там их несколько? Как раз для этого и нужен метод equals, который сравнивает объект, который Вы хотите получить, с тем, что содержится в списке и отдает именно Ваш объект. Отсюда следует очень важное правило — Два объекта могут иметь одинаковые хешкоды, но при этом не быть эквивалентными. Причем обратное утверждение не верно. Так как если два объекта эквивалентны, то и хешкоды у них совпадают.

Конкатенация строк

Очень частый вопрос на собеседованиях — «как правильно сцепить строки»? Ответ в следующем. Правильно создать строку из нескольких можно через объекты StringBuilder

или StringBuffer, а не через "+". Чем это объясняется. Во первых нужно помнить, что строки в Java — это immutable(неизменяемые) объекты. Т.е. при изменении значения созданного объекта, он не меняется, а создается новый объект с новым значением. Соответственно, создание строки следующим образом не лучшая идею:

String str = str1 + str2 + str3;

Как было написано выше, нужно использовать методы append классов StringBuilder и StringBuffer. Их различия заключаются лишь в том, что первый — синхронизированный, а второй — нет. Конечно, для одной строки, которая не используется в цикле, для лучшей читабельности кода лучше использовать пример, который был приведен выше.

Сравнение через "==" или «equals»

Все объекты в Java сравниваются только через equals. Через "==" сравниваются только примитивные типы. Также можно сравнивать числовые объекты в диапазоне от -128 до

127, так как уних предусмотрен механизм кеширования. Фактически, через "==" Вы сравниваете ссылки на объекты, а не сами объекты. Для того, чтобы это было понятнее — даже если два объекта одного класса и с одинаковым «содержимым», то они все равно не будут равны, тк ссылки у них не равны. Плюс метода equals также в том, что он позволяет определить свои способы сравнения объектов. По определенным полям или каким то другим параметрам.

Заключение

Вот и все, что я хотел рассказать Вам, уважаемы читатели. Надеюсь, что мои советы кому то помогут. Также очень многое для подготовки к собеседованию можно почерпнуть по этой ссылке. На сайте ibm вообще много хороших материалов по Java, по которым я сам когда то начинал изучение. Также в начале своего творческого пути почитайте Хорстмана «Java 2. Библиотека профессионала».

Автор: VladislavLysov

  1. Taras:

    Хороший матеріал. Дякую!

  2. Ольга:

    Поддерживаю все что в статье. По Java можно потестить себя на вопросах «327 вопроса на собеседование Java Developer»
    http://becomejavasenior.com/blog/2015/07/01/327-interview-questions-java-developer/

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js