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

Вопросы для интервью с системой типов Java

Набор вопросов для интервью, связанных с системой типов Java

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

1. введение

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

2. Вопросы

Q1. Опишите Место класса объектов в Иерархии типов. Какие типы наследуются от объекта, а какие нет? Наследуют ли массивы от объекта? Можно ли назначить Лямбда-выражение объектной переменной?

java.lang.Объект находится в верхней части иерархии классов в Java. Все классы наследуются от него либо явно, либо неявно (когда ключевое слово extends опущено в определении класса), либо транзитивно через цепочку наследования.

Однако существует восемь примитивных типов , которые не наследуются от Object , а именно boolean , byte , short , char , int , float , long и double .

Согласно спецификации языка Java, массивы также являются объектами. Они могут быть назначены ссылке Object , и на них могут быть вызваны все методы Object .

Лямбда-выражения не могут быть назначены непосредственно переменной Object , поскольку Object не является функциональным интерфейсом. Но вы можете назначить лямбду переменной функционального интерфейса, а затем назначить ее переменной Object (или просто назначить ее переменной объекта, одновременно приведя ее к функциональному интерфейсу).

Q2. Объясните Разницу Между Примитивными и ссылочными Типами.

Ссылочные типы наследуются от верхнего java.lang.Объект класс и сами являются наследуемыми (за исключением final классов). Примитивные типы не наследуются и не могут быть подклассами.

Примитивно типизированные значения аргументов всегда передаются через стек, что означает, что они передаются по значению, а не по ссылке. Это имеет следующее значение: изменения, внесенные в значение примитивного аргумента внутри метода, не распространяются на фактическое значение аргумента.

Примитивные типы обычно хранятся с использованием базовых типов аппаратных значений.

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

Размер заголовка объекта может быть довольно значительным по сравнению с размером простого числового значения. Вот почему примитивные типы были введены в первую очередь — для экономии места на накладных расходах объектов. Недостатком является то, что не все в Java технически является объектом — примитивные значения не наследуются от Object class.

Q3. Опишите Различные типы примитивов и объем памяти, который они занимают.

Java имеет 8 примитивных типов:

  • логическое — логическое true |/false значение. Размер boolean не определяется спецификацией JVM и может варьироваться в разных реализациях. байт
  • — знаковое 8-битное значение, короткое
  • — 16-битное значение со знаком, char
  • — 16-битное значение без знака, int
  • — 32-разрядное значение со знаком, long
  • — 64-разрядное значение со знаком, поплавок
  • — 32-битовое значение с плавающей запятой с одинарной точностью, соответствующее стандарту IEEE 754, двойной
  • — 64-битовое значение с плавающей запятой двойной точности, соответствующее стандарту IEEE 754.

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

Абстрактный класс-это класс с модификатором abstract в его определении. Он не может быть создан, но его можно подклассировать. Интерфейс-это тип, описываемый с помощью ключевого слова interface . Он также не может быть создан, но может быть реализован.

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

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

Класс abstract также может реализовать некоторые основные методы, необходимые во всех подклассах. Например, большинство коллекций карт в JDK наследуются от класса AbstractMap , который реализует множество методов, используемых подклассами (например, метод equals ).

Интерфейс определяет некоторый контракт, с которым соглашается класс. Реализованный интерфейс может означать не только основное намерение класса, но и некоторые дополнительные контракты.

Например, если класс реализует интерфейс Comparable , это означает, что экземпляры этого класса могут сравниваться, независимо от основной цели этого класса.

Q5. Каковы ограничения на элементы (Поля и методы) Типа интерфейса?

Интерфейс может объявлять поля, но они неявно объявляются как public , static и final , даже если вы не указываете эти модификаторы. Следовательно, вы не можете явно определить поле интерфейса как private . По сути, интерфейс может содержать только постоянные поля, а не поля экземпляра.

Все методы интерфейса также неявно public . Они также могут быть либо (неявно) абстрактными , либо по умолчанию .

Q6. В чем разница между Внутренним классом и Статическим вложенным классом?

Проще говоря, вложенный класс – это в основном класс, определенный внутри другого класса.

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

Вот пример внутреннего класса – вы можете видеть, что он может получить доступ к ссылке на экземпляр внешнего класса в виде OuterClass1.this construct:

public class OuterClass1 {

    public class InnerClass {

        public OuterClass1 getOuterInstance() {
            return OuterClass1.this;
        }

    }

}

Чтобы создать экземпляр такого внутреннего класса, вам необходимо иметь экземпляр внешнего класса:

OuterClass1 outerClass1 = new OuterClass1();
OuterClass1.InnerClass innerClass = outerClass1.new InnerClass();

Статический вложенный класс совсем другой. Синтаксически это просто вложенный класс с модификатором static в его определении.

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

public class OuterClass2 {

    public static class StaticNestedClass {
    }

}

Чтобы создать экземпляр такого класса, вам не нужен экземпляр внешнего класса:

OuterClass2.StaticNestedClass staticNestedClass = new OuterClass2.StaticNestedClass();

Q7. Имеет Ли Java Множественное Наследование?

Java не поддерживает множественное наследование классов, что означает, что класс может наследовать только от одного суперкласса.

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

Q8. Каковы классы обертки? Что Такое Автобоксинг?

Для каждого из восьми типов примитивов в Java существует класс-оболочка, который можно использовать для обертывания значения примитива и использования его как объекта. Эти классы, соответственно, Boolean , Byte , Short , Character , Integer , Float , Long и Double . Эти обертки могут быть полезны, например, когда вам нужно поместить примитивное значение в общую коллекцию, которая принимает только ссылочные объекты.

List list = new ArrayList<>();
list.add(new Integer(5));

Чтобы избежать проблем с ручным преобразованием примитивов туда и обратно, компилятор Java обеспечивает автоматическое преобразование, известное как автобокс/автоматическая распаковка.

List list = new ArrayList<>();
list.add(5);
int value = list.get(0);

Q9. Опишите разницу между equals() и ==

Это позволяет сравнить два объекта для “одинаковости” (т. Е. Чтобы обе переменные ссылались на один и тот же объект в памяти). Важно помнить, что ключевое слово new всегда создает новый объект, который не будет передавать равенство == с любым другим объектом, даже если они, кажется, имеют одинаковое значение:

String string1 = new String("Hello");
String string2 = new String("Hello");

assertFalse(string1 == string2);

Кроме того, позволяет сравнивать примитивные значения:

int i1 = 5;
int i2 = 5;

assertTrue(i1 == i2);

Метод equals() определен в java.lang.Объект класс и, следовательно, доступен для любого ссылочного типа. По умолчанию он просто проверяет, является ли объект тем же самым с помощью. Но обычно он переопределяется в подклассах, чтобы обеспечить определенную семантику сравнения для класса.

Например, для класса String этот метод проверяет, содержат ли строки одинаковые символы:

String string1 = new String("Hello");
String string2 = new String("Hello");

assertTrue(string1.equals(string2));

Q10. Предположим, У Вас Есть Переменная, которая ссылается на экземпляр типа класса. Как проверить, что Объект Является Экземпляром Этого класса?

В этом случае вы не можете использовать ключевое слово instanceof , потому что оно работает только в том случае, если вы указываете фактическое имя класса в качестве литерала.

К счастью, класс Class имеет метод isInstance , который позволяет проверить, является ли объект экземпляром этого класса:

Class integerClass = new Integer(5).getClass();
assertTrue(integerClass.isInstance(new Integer(4)));

Q11. Что такое Анонимный класс? Опишите Его Вариант Использования.

Анонимный класс-это одноразовый класс, который определяется в том же месте, где необходим его экземпляр. Этот класс определен и создан в одном и том же месте, поэтому ему не нужно имя.

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

Вот как вы можете создать и заполнить карту:

Map ages = new HashMap(){{
    put("David", 30);
    put("John", 25);
    put("Mary", 29);
    put("Sophie", 22);
}};