Вопросы по собеседованию в системе Java Type

Вопросы о системе типов Java

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

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

2. Вопросы

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

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

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

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

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

 

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

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

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

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

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

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

 

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

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

  • boolean - логическое значениеtrue /false. Размер логического значения не определен спецификацией JVM и может варьироваться в разных реализациях.

  • byte - 8-битное значение со знаком,

  • short - 16-битное значение со знаком,

  • char - беззнаковое 16-битное значение,

  • int - 32-битное значение со знаком,

  • long - 64-битное значение со знаком,

  • float - 32-битное значение с плавающей запятой одинарной точности, соответствующее стандарту IEEE 754,

  • double - 64-битное значение с плавающей запятой двойной точности, соответствующее стандарту IEEE 754.

 

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

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

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

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

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

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

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

 

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

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

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

 

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

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

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

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

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. Какие классы Wrapper? Что такое автобокс?

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

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

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

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.Object и поэтому доступен для любого ссылочного типа. По умолчанию он просто проверяет, является ли объект тем же с помощью оператора ==. Но это обычно переопределяется в подклассах, чтобы обеспечить определенную семантику сравнения для класса.

Например, для класса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);
}};