Рубрики
Без рубрики

Структура классов Java и вопросы для интервью с инициализацией

Набор общих упражнений для интервью из структуры классов и инициализации в Java

Автор оригинала: baeldung.

1. введение

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

Q1. Опишите Значение ключевого слова Final При применении к Классу, Методу, Полю или Локальной переменной.

Ключевое слово final имеет несколько различных значений при применении к различным языковым конструкциям:

  • Класс final – это класс, который не может быть подклассом
  • Метод final – это метод, который не может быть переопределен в подклассах
  • Поле final – это поле, которое должно быть инициализировано в блоке конструктора или инициализатора и не может быть изменено после этого
  • Переменная final – это переменная, которая может быть назначена (и должна быть назначена) только один раз и никогда не изменяется после этого

Q2. Что такое Метод по умолчанию?

До Java 8 интерфейсы могли иметь только абстрактные методы, т. Е. Методы без тела. Начиная с Java 8, методы интерфейса могут иметь реализацию по умолчанию. Если реализующий класс не переопределяет этот метод, то используется реализация по умолчанию. Такие методы соответствующим образом помечаются ключевым словом default .

Одним из известных случаев использования метода default является добавление метода в существующий интерфейс. Если вы не пометите такой метод интерфейса как default , то все существующие реализации этого интерфейса будут сломаны. Добавление метода с реализацией default обеспечивает двоичную совместимость устаревшего кода с новой версией этого интерфейса.

Хорошим примером этого является интерфейс Iterator , который позволяет классу быть целью цикла for-each. Этот интерфейс впервые появился в Java 5, но в Java 8 он получил два дополнительных метода, для каждого и spliterator . Они определены как методы по умолчанию с реализациями и, таким образом, не нарушают обратную совместимость:

public interface Iterable {

    Iterator iterator();

    default void forEach(Consumer action) { /* */ }

    default Spliterator spliterator() { /* */ }
}

Q3. Что Такое Статические Члены Класса?

Статические поля и методы класса не привязаны к конкретному экземпляру класса. Вместо этого они привязаны к самому объекту класса. Вызов метода static или обращение к полю static разрешается во время компиляции, поскольку, в отличие от методов и полей экземпляра, нам не нужно ходить по ссылке и определять фактический объект, на который мы ссылаемся.

Q4. Может Ли Класс Быть Объявлен Абстрактным, Если Он Не Имеет Абстрактных Членов? Какова может быть Цель Такого Класса?

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

Q5. Что Такое Цепочка Конструкторов?

Цепочка конструкторов – это способ упрощения построения объектов путем предоставления нескольких конструкторов, которые последовательно вызывают друг друга.

Наиболее конкретный конструктор может принимать все возможные аргументы и может использоваться для наиболее подробной конфигурации объекта. Менее конкретный конструктор может вызвать более конкретный конструктор, предоставив некоторым его аргументам значения по умолчанию. В верхней части цепочки конструктор без аргументов может создать экземпляр объекта со значениями по умолчанию.

Вот пример с классом, который моделирует скидку в процентах, доступную в течение определенного количества дней. Значения по умолчанию 10% и 2 дня используются, если мы не указываем их при использовании конструктора без аргументов:

public class Discount {

    private int percent;

    private int days;

    public Discount() {
        this(10);
    }

    public Discount(int percent) {
        this(percent, 2);
    }

    public Discount(int percent, int days) {
        this.percent = percent;
        this.days = days;
    }

}

Q6. Что такое переопределение и перегрузка методов? Чем Они Отличаются?

Переопределение метода выполняется в подклассе, когда вы определяете метод с той же сигнатурой, что и в суперклассе. Это позволяет среде выполнения выбирать метод в зависимости от фактического типа объекта, на котором вы вызываете метод. Методы toString , equals и hashCode довольно часто переопределяются в подклассах.

Перегрузка метода происходит в том же классе. Перегрузка возникает при создании метода с тем же именем, но с разными типами или количеством аргументов. Это позволяет выполнять определенный код в зависимости от типов аргументов, которые вы предоставляете, в то время как имя метода остается прежним.

Вот пример перегрузки в классе java.io.Writer abstract. Оба следующих метода имеют имена write , но один из них получает int , а другой-массив char .

public abstract class Writer {

    public void write(int c) throws IOException {
        // ...
    }

    public void write(char cbuf[]) throws IOException {
        // ...
    }

}

Q7. Можете ли Вы переопределить статический метод?

Нет, ты не можешь. По определению, переопределить метод можно только в том случае, если его реализация определяется во время выполнения типом фактического экземпляра (процесс, известный как поиск динамического метода). Реализация метода static определяется во время компиляции с использованием типа ссылки, поэтому переопределение в любом случае не имеет большого смысла. Хотя вы можете добавить в подкласс метод static с той же сигнатурой, что и в суперклассе, это технически не переопределяет.

Q8. Что Такое Неизменяемый класс и как Его можно создать?

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

Чтобы сделать класс неизменяемым, вы должны обеспечить следующее:

  • Все поля должны быть объявлены private и final ; это означает, что они должны быть инициализированы в конструкторе и с тех пор не изменяться;
  • В классе не должно быть сеттеров или других методов, которые изменяют значения полей;
  • Все поля класса, которые были переданы через конструктор, должны быть либо также неизменяемыми, либо их значения должны быть скопированы до инициализации поля (или же мы могли бы изменить состояние этого класса, удерживая эти значения и изменяя их);
  • Методы класса не должны быть переопределяемыми; либо все методы должны быть final , либо конструктор должен быть private и вызываться только через static factory метод.

Q9. Как Вы сравниваете два значения перечисления: С Equals() или с ==?

На самом деле, вы можете использовать и то, и другое. Значения enum являются объектами, поэтому их можно сравнить с equals() , но они также реализованы как статические константы под капотом, поэтому вы также можете сравнить их с == . В основном это вопрос стиля кода, но если вы хотите сэкономить пространство символов (и, возможно, пропустить ненужный вызов метода), вам следует сравнить перечисления с == .

Q10. Что такое Блок инициализатора? Что такое Статический блок инициализатора?

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

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

Блок статического инициализатора-это блок кода с фигурными скобками и модификатором static перед ним. Он выполняется один раз во время загрузки класса и может использоваться для инициализации статических полей или для некоторых побочных эффектов.

Q11. Что такое Интерфейс Маркера? Каковы заметные примеры интерфейсов маркеров в Java?

Интерфейс маркера-это интерфейс без каких-либо методов. Обычно он реализуется классом или расширяется другим интерфейсом для обозначения определенного свойства. Наиболее широко известными интерфейсами маркеров в стандартной библиотеке Java являются следующие:

  • Сериализуемый используется для явного выражения того, что этот класс может быть сериализован;
  • Cloneable позволяет клонировать объекты с помощью метода clone (без интерфейса Cloneable этот метод вызывает исключение CloneNotSupportedException );
  • Remote используется в RMI для указания интерфейса, методы которого могут вызываться удаленно.

Q12. Что такое Синглтон и как он может быть реализован в Java?

Синглтон-это шаблон объектно-ориентированного программирования. Одноэлементный класс может иметь только один экземпляр, обычно глобально видимый и доступный.

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

public class SingletonExample {

    private static SingletonExample instance = new SingletonExample();

    private SingletonExample() {}

    public static SingletonExample getInstance() {
        return instance;
    }
}

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

Q13. Что такое ВарАрг? Каковы ограничения на Вар-Арг? Как Вы Можете Использовать Его Внутри Тела Метода?

Var-arg-это аргумент переменной длины для метода. Метод может иметь только один var-arg, и он должен быть последним в списке аргументов. Он указывается в виде имени типа, за которым следует многоточие и имя аргумента. Внутри тела метода в качестве массива указанного типа используется var-arg.

Вот пример из стандартной библиотеки — метод Collections.addAll , который получает коллекцию, переменное количество элементов и добавляет все элементы в коллекцию:

public static  boolean addAll(
  Collection c, T... elements) {
    boolean result = false;
    for (T element : elements)
        result |= c.add(element);
    return result;
}

Q14. Можете ли Вы получить доступ к переопределенному методу суперкласса? Можете ли Вы Получить доступ к Переопределенному методу Суперкласса аналогичным образом?

Для доступа к переопределенному методу суперкласса можно использовать ключевое слово super . Но у вас нет аналогичного способа доступа к переопределенному методу суперкласса.

В качестве примера из стандартной библиотеки класс LinkedHashMap расширяет HashMap и в основном уменьшает его функциональность, добавляя связанный список поверх его значений, чтобы сохранить порядок итераций. LinkedHashMap повторно использует метод clear своего суперкласса, а затем очищает головные и хвостовые ссылки своего связанного списка:

public void clear() {
    super.clear();
    head = tail = null;
}