JavaRush /Blog Java /Random-ES /Núcleo de Java. Preguntas de la entrevista, parte 1
Andrey
Nivel 26

Núcleo de Java. Preguntas de la entrevista, parte 1

Publicado en el grupo Random-ES
Para quienes escuchan la palabra Java Core por primera vez, estos son los fundamentos fundamentales del lenguaje. Con este conocimiento, puede realizar con seguridad una pasantía/prácticas. Núcleo de Java.  Preguntas de la entrevista, parte 1 - 1Estas preguntas le ayudarán a actualizar sus conocimientos antes de la entrevista o a aprender algo nuevo por sí mismo. Para adquirir habilidades prácticas, estudie en JavaRush .
  1. ¿Cómo crear un objeto inmutable en Java? Enumere todos los beneficios

    Una clase inmutable es una clase cuyo estado no se puede cambiar después de la creación. Aquí, se considera esencialmente que el estado de un objeto son los valores almacenados en una instancia de una clase, ya sean tipos primitivos o tipos de referencia.

    Para que una clase sea inmutable, se deben cumplir las siguientes condiciones:

    1. No proporcione definidores ni métodos que modifiquen campos u objetos que hagan referencia a campos. Los establecedores implican cambiar el estado de un objeto, que es lo que queremos evitar aquí.
    2. Haga todos los campos finaly private. privateNo se podrá acceder a los campos marcados desde fuera de la clase y marcarlos finalgarantiza que no los cambiará, ni siquiera por accidente.
    3. No permita que las subclases anulen métodos. La forma más sencilla de hacerlo es declarar la clase como final. Las clases finalizadas en Java no se pueden anular.
    4. Recuerde siempre que sus instancias variables pueden ser mutables o inmutables. Defínalos y devuelva nuevos objetos con contenido copiado para todos los objetos mutables (tipos de referencia). Las variables inmutables (tipos primitivos) se pueden devolver de forma segura y sin esfuerzo adicional.

    Además, es necesario recordar los beneficios posteriores de las clases inmutables. Es posible que los necesite en una entrevista. Clases inmutables:

    • fácil de diseñar, probar y usar
    • Automáticamente seguro para subprocesos y no tiene problemas de sincronización.
    • no requiere un constructor de copia
    • le permite inicializar perezosamente un código hash y almacenar en caché el valor de retorno
    • no requiere copia segura cuando se utiliza como campo
    • hacer buenas Mapclaves y Setelementos (estos objetos no deben cambiar de estado mientras estén en la colección)
    • haga que su clase sea permanente creándola una vez, y no es necesario verificarla nuevamente
    • siempre tienen “atomicidad de falla” (un término acuñado por Joshua Bloch): si un objeto inmutable genera una excepción, nunca permanecerá en un estado no deseado o indefinido.

    Mira el ejemplo escrito en esta publicación .

  2. En Java, ¿pasar por valor o por referencia?

    Java спецификация гласит, что все в Java передается по значению. Нет такого понятия, Cómo «передача по ссылке» в Java. Эти условия связаны с вызовом методов и передачей переменных, Cómo параметров метода. Хорошо, примитивные типы всегда передаются по значению без Cómoой-либо путаницы. Но, концепция должна быть понятна в контексте параметра метода сложных типов.

    В Java, когда мы передает ссылку сложного типа Cómo любой параметр метода, всегда DIRECCIÓN памяти копируется в новую ссылочную переменную шаг за шагом. Посмотрите на изображение:

    Núcleo de Java.  Preguntas de la entrevista, partes 1 - 2

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

    Подробности смотрите тут.

  3. Какое применение блока finally? Гарантирует этот блок выполнение своего códigoа? Когда finally блок не вызывается?

    Блок finally всегда вызывается, если блок try существует. Это гарантирует, что блок finally вызывается даже, если случается неожиданное исключение. Но finally является более полезным, чем просто для обработки исключений – этот блок позволяет выполнить чистку códigoа, случайно обошедшего через return, continue o break. Размещение очищающего códigoа в блок finally всегда является хорошей практикой, даже когда не ожидается ниCómoих исключений.

    Если виртуальная машина завершает работу во время выполнения блока try o catch, тогда блок finally не будет выполнен. Аналогично, если нить, выполняя блок try o catch, будет прервана o убита, блок finally не будет выполнен, даже не смотря на то, что приложение продолжает работать.

  4. Почему существует два класса Date, один в java.util package а другой в java.sql?

    java.util.Date представляет fecha и время, а java.sql.Date представляет только fecha. Дополнением к java.sql.Date является класс java.sql.Time, который представляет только время.

    Класс java.sql.Date является субклассом (расширением) класса java.util.Date. Итак, что изменилось в java.sql.Date:

    • toString() формирует другое представление строки: yyyy-mm-dd
    • статический метод valueOf(String) создает fecha из строки с вышеуказанным представлением
    • исключены геттеры и сеттеры для часов, minutos и секунд

    Класс java.sql.Date используется в JDBC и предназначен, чтобы не иметь составляющую времени, то есть часы, minutosы, секунды и миллисекунды должны быть нулю… но это не является обязательным для класса.

  5. Разъясните интерфейсы-маркеры.

    Шаблон интерфейса-маркера – это шаблон проектирования в компьютерных науках, используемый языками программирования, которые предоставляют информацию об un objetoах во время выполнения. Это предоставляет способ ассоциации метаданных класса, где язык не имеет явной поддержки таких метаданных. В Java для этого используются интерфейсы без указания методов.

    Хорошим примером применения интерфейса-маркера в Java является интерфейс Serializable. Класс реализует этот интерфейс для указания, что его не transient данные могут быть записаны в поток byteов o на файловую систему.

    Главной проблемой интерфейса-маркера является то, что интерфейс определяет соглашение для реализующих его классов, и это соглашение наследуется всеми субклассами. Это значит, что вы не сможете «де-реализовать» маркер. В приведенном примере, если вы создадите субкласс, который вы бы не хотели сериализовать (возможно потому, что он находится в преходящем (transient) состоянии), вы должны прибегнуть к явному бросанию NotSerializableException.

  6. Почему метод main() объявлен Cómo public static void?

    Почему public? Метод main имеет модификатор доступа public, поэтому он может быть доступен везде и для любого un objetoа, который захочет использовать этот метод для запуска aplicaciones. Тут я не говорю, что JDK/JRE имеют подобный повод, поскольку java.exe o javaw.exe (для windows) используют Java Native Interface (JNI) вызов для запуска метода, поэтому они могут вызвать его в любом случае, независимо от модификатора доступа.

    Почему static? Давайте предположим, что у нас метод main не статический. Теперь, для вызова любого метода вам необходим экземпляр класса. Верно? Java разрешает иметь перегруженные конструкторы, это мы все знаем. Тогда который из них должен быть использован, и откуда возьмутся параметры для перегруженного конструктора?

    Почему void? Нет применения для возвращаемого значения в виртуальной машине, которая фактически вызывает этот метод. Единственное, что приложение захочет сообщить вызвавшему процессу – это нормальное o ненормальное завершение. Это уже возможно используя System.exit(int). Не нулевое significado подразумевает ненормальное завершение, иначе все в порядке.

  7. В чем разница между созданием строки Cómo new() и литералом (при помощи двойных кавычек)?

    Когда мы создаем строку используя new(), она создается в хипе и также добавляется в пул строк, в то же время строка, созданная при помощи литерала, создается только в пуле строк.

    Вам необходимо ознакомиться с понятием пула строк глубже, чтобы ответить на этот o подобные вопросы. Мой совет – Cómo следует выучите класс String и пул строк.

    У нас в переводах уже есть хорошая статья о строках и строковом пуле: Часть 1, Часть 2.
  8. Как работает метод substring() класса String?

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

    /** The value is used for character storage. */
    /** Значение используется для хранения символов */
    private final char value[];
    Для доступа к этому массиву в различных сценариях используются следующие переменные/** The offset is the first index of the storage that is used. */
    /** Смещение – это первый индекс используемого хранoща. */
    private final int offset;
    
    /** The count is the number of characters in the String. */
    /** Счет – это количество символов в строке. */
    private final int count;

    Каждый раз, когда мы создаем подстроку от существующего экземпляра строки, метод substring() только устанавливает новые значения переменных offset и count. Внутренний массив символов не изменяется. Это возможный источник утечки памяти, если метод substring() использовать неосторожно:

    Первоначальное significado value[] не изменяется. Поэтому если вы создадите строку длиной 10000 символов и создадите 100 подстрок с 5-10 символами в каждой, все 101 un objetoы будут содержать один и тот же символьный массив длиной 10000 символов. Это без сомнения расточительство памяти.

    Этого можно избежать, изменив código следующим образом:

    заменить original.substring(beginIndex) на new String(original.substring(beginIndex)), где original – исходная строка.

    Примечание переводчика: я затрудняюсь сказать к Cómoой версии Java это применимо, но на данный момент в Java 7 этот пункт статьи не актуален. Метод substring() вызывает конструктор класса new String(value, beginIndex, subLen), который в свою очередь обращается к методу Arrays.copyOfRange(value, offset, offset+count). Это значит, что у нас будет каждый раз новое significado переменной value[], содержащее наше новое количество символов.
  9. Объясните работу HashMap. Как решена проблема дубликатов?

    Большинство из вас наверняка согласится, что HashMap наиболее любимая тема для дискуссий на интервью в настоящее время. Если кто-нибудь попросит меня рассказать «Как работает HashMap?», я просто отвечу: «По принципу хэширования». Так просто, Cómo это есть.

    Итак, хеширование по сути является способом назначить уникальный código для любой переменной/un objetoа после применения любой формулы/алгоритма к своим свойствам.

    Определение карты (Map) таково: «Объект, который привязывает ключи к значениям». Очень просто, верно? Итак, HashMap содержит собственный внутренний класс Entry, который имеет вид:

    static class Entry implements Map.Entry
    {
    final K key;
    V value;
    Entry next;
    final int hash;//More code goes here
    }

    Когда кто-либо пытается поместить пару ключ-significado в HashMap, происходит следующее:

    • В первую очередь, un objeto ключа проверяется на null. Если ключ null, significado сохраняется в позицию table[0]. Потому что хэшcódigo для null всегда 0.
    • Затем, следующим шагом вычисляется хэш significado вызывая у переменной-ключа свой метод hashCode(). Этот хэш используется для вычисления индекса в массиве для хранение un objetoа Entry. Разработчики JDK прекрасно понимали, что метод hashCode() может быть плохо написан и может возвращать очень большое o очень маленькое significado. Для решения этой проблемы они ввели другой hash() метод, и передают хэшcódigo un objetoа этому методу для приведения этого значения к диапазону размера индекса массива.
    • Теперь вызывается метод indexFor(hash, table.length) для вычисления точной позиции для хранения un objetoа Entry.
    • Теперь главная часть. Как мы знаем, два неодинаковых un objetoа могут иметь одинаковое significado хэшcódigoа, Cómo два разных un objetoа будет храниться в одинаковом расположении в архиве [называется корзиной]?

    Ответ – LinkedList. Если вы помните, класс Entry имеет свойство “next”. Это свойство всегда указывает на следующий un objeto в цепи. Такое поведение очень похоже на LinkedList.

    Итак, в случае совпадений хэшcódigoов, un objetoы Entry хранятся в форме LinkedList. Когда un objeto Entry необходимо разместить на конкретном индексе, HashMap проверяет, существует ли на этом месте другой un objeto Entry? Если там нет записи, наш un objeto сохранится в этом месте.

    Если на нашем индексе уже находится другой un objeto, проверяется его поле next. Если оно равно null, наш un objeto становится следующим узлом в LinkedList. Если next не равно null, эта procedimientosа повторяется, пока не будет найдено поле next равное null.

    Qué будет, если мы добавим другое significado ключа, равное добавленному ранее? Логично, что оно должно заменить старое significado. Как это происходит? После определения индекса позиции для un objetoа Entry, пробегая по LinkedList, расположенному на нашем индексе, HashMap вызывает метод equals() для значения ключа для каждого un objetoа Entry. Все эти un objetoы Entry в LinkedList имеют одинаковое significado хэшcódigoа, но метод equals() будет проверять на настоящее es igualство. Если ключ.equals(k) будет true, тогда оба будут восприниматься Cómo одинаковый un objeto. Это вызовет замену только un objetoа-significado внутри un objetoа Entry.

    Таким образом HashMap обеспечивает уникальность ключей.

  10. Различия между интерфейсами и абстрактными классами?

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

    • В интерфейсах Java переменные априори final. Абстрактные классы могут содержать не final переменные.
    • Интерфейс в Java безоговорочно не может иметь реализации. Абстрактный класс может иметь экземпляры методов, которые реализуют базовое поведение.
    • Составляющие интерфейса должны быть public. Абстрактный класс может иметь модификаторы доступа на любой вкус.
    • Интерфейс должен быть реализован ключевым словом implements. Абстрактный класс должен быть расширен при помощи ключевого слова extends.
    • В Java класс может реализовывать множество интерфейсов, но может унаследоваться только от одного абстрактного класса.
    • Интерфейс completamente абстрактный и не может иметь экземпляров. Абстрактный класс также не может иметь экземпляров класса, но может быть вызван, если существует метод main().
    • Una clase abstracta es ligeramente más rápida que una interfaz porque la interfaz asume una búsqueda antes de llamar a cualquier método anulado en Java. En la mayoría de los casos, esta es una diferencia menor, pero si está escribiendo una aplicación en la que el tiempo es crítico, debe tener en cuenta este hecho.
  11. ¿Cuándo se anulan los métodos hashCode()y equals()?

    Los métodos hashCode()y equals()se definen en la clase Object, que es la clase principal de todos los objetos Java. Por este motivo, todos los objetos Java heredan la implementación subyacente de estos métodos.

    El método hashCode()se utiliza para obtener un valor entero único para un objeto determinado. Este valor se utiliza para determinar la ubicación de la papelera de reciclaje cuando el objeto debe almacenarse en una estructura de datos como HashTable. De forma predeterminada, el método hashCode()devuelve una representación entera de la dirección de memoria donde está almacenado el objeto.

    El método equals(), como su nombre indica, se utiliza para la equivalencia de objetos simples. La implementación básica del método es verificar las referencias de dos objetos para comprobar si son equivalentes.

    Tenga en cuenta que normalmente es necesario anular un método hashCode()cada vez que se anula un método equals(). Esto es necesario para respaldar la convención general del método hashCode, que establece que objetos iguales deben tener códigos hash iguales.

    El método equals() debe determinar la igualdad entre relaciones (debe ser recurrente, simétrico y transitivo). Además, debe ser persistente (si el objeto no ha cambiado, el método debe devolver el mismo valor). Además, o.equals(null)siempre debería devolver false .

    hashCode()También debe ser persistente (si el objeto no ha cambiado bajo las condiciones del método equals(), debe continuar devolviendo el mismo valor.

    La relación entre los dos métodos es: siempre, si a.equals(b), entonces a.hashCode()debe ser igual que b.hashCode().

¡¡Buena suerte con sus estudios!! Autor del artículo Lokesh Gupta Artículo original Enlaces a otras partes: Java Core. Preguntas de la entrevista, parte 2 Java Core. Preguntas para una entrevista, parte 3
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION