Вопросы о структуре класса Java и вопросы инициализации

1. Вступление

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

Q1. Опишите значение ключевого слова final применительно к классу, методу, полю или локальной переменной.

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

  • Final класс - это класс, который нельзя разделить на подклассы

  • Final метод - это метод, который не может быть переопределен в подклассах

  • Поле final - это поле, которое должно быть инициализировано в

блок конструктора или инициализатора и после этого не может быть изменен ** Переменная final - это переменная, которая может быть назначена (и должна быть

назначается) только один раз и никогда не изменяется после этого

Q2. Что такое метод default ?

До Java 8 интерфейсы могли иметь только абстрактные методы, т.е.

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

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

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

public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {/**  ** /}

    default Spliterator<T> spliterator() {/**  ** /}
}

Q3. Что такое static ученики?

Static поля и методы класса не привязаны к конкретному экземпляру класса. Вместо этого они связаны с самим объектом класса.

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

Q4. Можно ли объявить класс абстрактным, если у него нет абстрактных членов? Какова может быть цель такого класса?

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

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 .

Следующие методы оба названы write , но один из них получает int , а другой получает массив char .

public abstract class Writer {

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

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

}

Q7. Можете ли вы переопределить метод static ?

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

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

Экземпляр неизменяемого класса нельзя изменить после его создания.

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

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

  • Все поля должны быть объявлены private и final ; это означает, что

они должны быть инициализированы в конструкторе и никогда не изменяться поскольку; ** В классе не должно быть сеттеров или других методов, которые изменяют

значения полей; ** Все поля класса, которые были переданы через конструктор, должны либо

быть также неизменным, или их значения должны быть скопированы перед полем инициализация (или мы могли бы изменить состояние этого класса удерживая эти значения и изменяя их); ** Методы класса не должны быть переопределенными; либо все методы

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

Q9. Как сравнить два значения enum : с equals () или с == ?

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

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

Q10. Что такое блок инициализатора? Что такое блок инициализатора static ?

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

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

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

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

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

  • Serializable используется для явного выражения, что этот класс может быть

сериализованная; ** Cloneable позволяет клонировать объекты, используя метод clone (без

Cloneable интерфейс на месте, этот метод выдает CloneNotSupportedException ); ** Remote используется в RMI для указания интерфейса, какие методы могут быть

называется удаленно.

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

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

Существует несколько способов создания синглтона в Java. Ниже приведен самый простой пример с полем static , которое инициализируется на месте. Инициализация является поточно-ориентированной, поскольку поля 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 <T> boolean addAll(
  Collection<? super T> c, T... elements) {
    boolean result = false;
    for (T element : elements)
        result |= c.add(element);
    return result;
}

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

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

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

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

Следующий "

  • «** Предыдущая

https://www.baeldung.com/java-concurrency-interview-questions [Java Вопросы о параллельном интервью (ответы)