JavaRush /Java Blog /Random-TL /Pagsusuri ng mga tanong at sagot mula sa mga panayam para...

Pagsusuri ng mga tanong at sagot mula sa mga panayam para sa developer ng Java. Bahagi 7

Nai-publish sa grupo
Hoy lahat! Ang programming ay puno ng mga pitfalls. At halos walang paksa kung saan hindi ka madadapa at mabunggo. Ito ay totoo lalo na para sa mga nagsisimula. Ang tanging paraan upang mabawasan ito ay ang pag-aaral. Sa partikular, nalalapat ito sa mga detalyadong pagsusuri sa mga pinakapangunahing paksa. Ngayon ay patuloy kong sinusuri ang 250+ na tanong mula sa mga panayam ng developer ng Java, na sumasaklaw nang mabuti sa mga pangunahing paksa. Gusto kong tandaan na ang listahan ay naglalaman din ng ilang hindi karaniwang mga tanong na nagbibigay-daan sa iyong tingnan ang mga karaniwang paksa mula sa ibang anggulo.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 1

62. Ano ang string pool at bakit ito kailangan?

Sa memorya sa Java (Heap, na pag-uusapan natin mamaya) mayroong isang lugar - String pool , o string pool. Ito ay dinisenyo upang mag-imbak ng mga halaga ng string. Sa madaling salita, kapag lumikha ka ng isang tiyak na string, halimbawa sa pamamagitan ng double quotes:
String str = "Hello world";
Ang isang pagsusuri ay ginawa upang makita kung ang string pool ay may ibinigay na halaga. Kung gayon, ang str variable ay itinalaga ng isang reference sa value na iyon sa pool. Kung hindi, gagawa ng bagong value sa pool, at isang reference dito ang itatalaga sa str variable . Tingnan natin ang isang halimbawa:
String firstStr = "Hello world";
String secondStr = "Hello world";
System.out.println(firstStr == secondStr);
true ay ipapakita sa screen . Naaalala namin na ang == ay naghahambing ng mga sanggunian—ibig sabihin ang dalawang sanggunian na ito ay tumutukoy sa parehong halaga mula sa string pool. Ginagawa ito upang hindi makagawa ng maraming magkakaparehong bagay ng uri ng String sa memorya, dahil gaya ng natatandaan natin, ang String ay isang hindi nababagong klase, at kung marami tayong reference sa parehong halaga, walang mali doon. Hindi na posible para sa isang sitwasyon kung saan ang pagbabago ng isang halaga sa isang lugar ay humahantong sa mga pagbabago para sa ilang iba pang mga link nang sabay-sabay. Ngunit gayunpaman, kung lumikha tayo ng isang string gamit ang bagong :
String str = new String("Hello world");
isang hiwalay na bagay ang gagawin sa memorya na mag-iimbak ng halaga ng string na ito (at hindi mahalaga kung mayroon na tayong ganoong halaga sa string pool). Bilang kumpirmasyon:
String firstStr = new String("Hello world");
String secondStr = "Hello world";
String thirdStr = new String("Hello world");
System.out.println(firstStr == secondStr);
System.out.println(firstStr == thirdStr);
Makakakuha kami ng dalawang maling halaga , na nangangahulugang mayroon kaming tatlong magkakaibang mga halaga dito na tinutukoy. Sa totoo lang, ito ang dahilan kung bakit inirerekomenda na lumikha ng mga string gamit lamang ang double quotes. Gayunpaman, maaari kang magdagdag (o makakuha ng sanggunian sa) mga halaga sa isang string pool kapag lumilikha ng isang bagay gamit ang bagong . Upang gawin ito, ginagamit namin ang string class method - intern() . Ang pamamaraang ito ay puwersahang lumilikha ng isang halaga sa string pool, o nakakakuha ng isang link dito kung ito ay nakaimbak na doon. Narito ang isang halimbawa:
String firstStr = new String("Hello world").intern();
String secondStr = "Hello world";
String thirdStr = new String("Hello world").intern();
System.out.println(firstStr == secondStr);
System.out.println(firstStr == thirdStr);
System.out.println(secondStr == thirdStr);
Bilang resulta, makakatanggap kami ng tatlong totoong halaga sa console , na nangangahulugan na ang lahat ng tatlong variable ay tumutukoy sa parehong string.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 2

63. Anong mga pattern ng GOF ang ginagamit sa string pool?

В строковом пуле явно прослеживается GOF шаблон — легковес (flyweight), иначе его называют поселенец. Если же вы увидели тут ещё Howой-то шаблон — делитесь в комментарии. Ну а мы поговорим о шаблоне легковесе. Легковес — структурный шаблон проектирования, при котором an object, представляющий себя How уникальный экземпляр в разных местах программы, по факту не является таковым. Легковес экономит память, разделяя общее состояние an objectов между собой, instead of хранения одинаковых данных в каждом an objectе. Для понимания сути рассмотрим самый простой пример. Предположим, у нас есть интерфейс сотрудника:
public interface Employee {
   void work();
}
И есть некоторые реализации, например, юрист:
public class Lawyer implements Employee {

   public Lawyer() {
       System.out.println("Юрист взят в штат.");
   }

   @Override
   public void work() {
       System.out.println("Решение юридических вопросов...");
   }
}
И бухгалтер:
public class Accountant implements Employee{

   public Accountant() {
       System.out.println("Бухгалтер взят в штат.");
   }

   @Override
   public void work() {
       System.out.println("Ведение бухгалтерского отчёта....");
   }
}
Методы весьма условны: нам всего лишь нужно видеть, что они выполняются. Такая же ситуация и с конструктором. Благодаря выводу в консоли мы будем видеть, когда создаются новые an objectы. Также у нас есть отдел сотрудников, задача которого — выдавать запрашиваемого сотрудника, если же его нет — нанимать в штат и выдавать в ответ на request:
public class StaffDepartment {
   private Map<String, Employee> currentEmployees = new HashMap<>();

   public Employee receiveEmployee(String type) throws Exception {
       Employee result;
       if (currentEmployees.containsKey(type)) {
           result = currentEmployees.get(type);
       } else {
           switch (type) {
               case "Бухгалтер":
                   result = new Accountant();
                   currentEmployees.put(type, result);
                   break;
               case "Юрист":
                   result = new Lawyer();
                   currentEmployees.put(type, result);
                   break;
               default:
                   throw new Exception("Данный сотрудник в штате не предусмотрен!");
           }
       }
       return result;
   }
}
То есть логика простая: если есть данная единица — верни её, если нет — создай, помести в хранorще (что-то вроде кеша) и отдай назад. А теперь давайте посмотрим, How это всё работает:
public static void main(String[] args) throws Exception {
   StaffDepartment staffDepartment = new StaffDepartment();
   Employee empl1  = staffDepartment.receiveEmployee("Юрист");
   empl1.work();
   Employee empl2  = staffDepartment.receiveEmployee("Бухгалтер");
   empl2.work();
   Employee empl3  = staffDepartment.receiveEmployee("Юрист");
   empl1.work();
   Employee empl4  = staffDepartment.receiveEmployee("Бухгалтер");
   empl2.work();
   Employee empl5  = staffDepartment.receiveEmployee("Юрист");
   empl1.work();
   Employee empl6  = staffDepartment.receiveEmployee("Бухгалтер");
   empl2.work();
   Employee empl7  = staffDepartment.receiveEmployee("Юрист");
   empl1.work();
   Employee empl8  = staffDepartment.receiveEmployee("Бухгалтер");
   empl2.work();
   Employee empl9  = staffDepartment.receiveEmployee("Юрист");
   empl1.work();
   Employee empl10  = staffDepartment.receiveEmployee("Бухгалтер");
   empl2.work();
}
И в консоли, соответственно, будет вывод:
Юрист взят в штат. Решение юридических вопросов... Бухгалтер взят в штат. Ведение бухгалтерского отчёта.... Решение юридических вопросов... Ведение бухгалтерского отчёта.... Решение юридических вопросов... Ведение бухгалтерского отчёта.... Решение юридических вопросов... Ведение бухгалтерского отчёта.... Решение юридических вопросов... Ведение бухгалтерского отчёта...
Как вы видите, всего было создано лишь два an object, которые при этом многократно переиспользовались. Пример весьма простой, но он наглядно демонстрирует How применение данного шаблона может сэкономить наши ресурсы. Ну и How вы заметor, логика данного паттерна уж больно похожа на логику работы страхового пула. Подробнее о разновидностях GOF паттернов вы можете почитать в этой статье.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 3

64. Как разделить строку на части? Приведите пример соответствующего codeа

Очевидно, что в данном вопросе речь идёт о методе split. У класса String есть две вариации данного метода:
String split(String regex);
и
String split(String regex);
regex — это разделитель строки — некоторое регулярное выражение, по которому производится разделение строки на массив строк, например:
String str = "Hello, world it's Amigo!";
String[] arr = str.split("\\s");
for (String s : arr) {
  System.out.println(s);
}
В консоль будет выведено:
Hello, world it's Amigo!
То есть, наше строковое meaning было разбито на массив строк и разделителем послужил пробел (для разделения можно было использовать и не регулярное выражение пробела "\\s" и просто строковое выражение " "). Второй, перегруженный метод имеет дополнительный аргумент — limit. limit — максимально допустимое meaning получаемого массива. То есть, когда строка будет уже разбита на предельное допустимое количество подстрок, дальнейшей разбивки не будет, и у последнего element будет “остаток” от возможно недоразбитой строки. Пример:
String str = "Hello, world it's Amigo!";
String[] arr = str.split(" ", 2);
for (String s : arr) {
  System.out.println(s);
}
Вывод в консоли:
Hello, world it's Amigo!
Как мы видим, если бы не ограничение limit = 2, последний элемент массива можно было бы разбить на три подстроки.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 4

65. Почему массив символов лучше строки для сохранения пароля?

Причин для предпочтения массива строке при сохранении пароля несколько: 1. Строковой пул и неизменяемость строк. При использовании массива (char[]) мы можем явно стереть данные после того, How закончor работу с ним. Также мы можем сколько угодно переписывать массив, и действительного пароля нигде не будет в системе, даже до сбора мусора (достаточно изменить пару ячеек на недействительные значения). В то самое время String — immutable класс. То есть, если мы хотим изменить его meaning, мы получим новое, а старое при этом останется в строковом пуле. Если мы захотим удалить String meaning пароля, это может быть весьма сложным занятием, так How нужно, чтобы сборщик мусора удалил именно meaning из String pool-а, и существует большая вероятность, что это String meaning останется там надолго. То есть, в данной ситуации String уступает массиву char в безопасности хранения данных. 2. При случайном выводе в консоли (or в логи) значения String выведется само meaning:
String password = "password";
System.out.println("Пароль - " + password);
Вывод в консоли:
Пароль - password
В то же время, если случайно вывести в консоль массив:
char[] arr = new char[]{'p','a','s','s','w','o','r','d'};
System.out.println("Пароль - " + arr);
в консоли будет непонятная абракадабра:
Пароль - [C@7f31245a
На самом деле не абракадабра, а: [C — Name класса — массив char, @ — разделитель, после которого — 7f31245a — шестнадцатеричный хешcode. 3. Официальный document, руководство по архитектуре криптографии Java прямо указывает на хранение паролей в char[] instead of String: “Казалось бы, логично собрать и сохранить пароль в an objectе типа java.lang.String. Однако здесь есть предостережение: an objectы типа String неизменяемы, т. е. Не определены методы, позволяющие изменять (перезаписывать) or обнулять содержимое an object String после использования. Эта функция делает String an objectы непригодными для хранения конфиденциальной информации, такой How пароли пользователей. Вместо этого вы всегда должны собирать и хранить конфиденциальную информацию о безопасности в массиве символов.”Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 5

Enum

66. Дайте краткую характеристику Enum в Java

Enum — перечисление, набор строковых констант, объединенных общим типом. Объявляется через ключевое слово — enum. Вот пример с enum — допустимые роли в некоторой школе:
public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD
}
Слова, написанные большими буквами, и есть те самые константы перечисления, которые объявляются упрощенно, без использования оператора new. Использование перечислений заметно упрощает жизнь, так How они помогают избежать ошибок и путаницы в наименованиях (так How может быть только определенный перечень значений). Лично для меня они очень удобны при использовании в логической конструкции Switch.

67. Может Enum реализовывать (implements) интерфейсы?

Да. Ведь перечисления должны представлять не просто пассивные наборы (How например, роли). В Java они могут представлять более сложные an objectы с некоторым функционалом, поэтому вам, возможно, понадобится добавить к ним дополнительный функционал. Также это позволит использовать возможности полиморфизма, подставляя meaning enum в места, где необходим тип имплементируемого интерфейса.

68. Может Enum расширять (extends) класс?

Нет, не может, так How перечисление — это подкласс по умолчанию универсального класса Enum <T>, где T представляет универсальный тип перечисления. Это не что иное, How общий базовый класс для всех типов перечисления языка Java. Преобразование enum в класс выполняется компилятором Java во время компиляции. Это расширение явно в codeе не указывается, но всегда незримо присутствует.

69. Можно ли создать Enum без экземпляров an objectов?

Как по мне, вопрос немного странный, ну or я его не до конца понял. У меня есть две интерпретации: 1. Может ли быть enum без значений — да, конечно, это будет что-то вроде пустого класса — бессмысленно:
public enum Role {
}
И вызвав:
var s = Role.values();
System.out.println(s);
Мы получим в консоли:
[Lflyweight.Role;@9f70c54
(пустой массив значений Role) 2. Можно ли создать enum без оператора new — да, конечно. Как я выше уже сказал, для значений (перечислений) enum не нужно использовать оператор new, так How это — статические значения.

70. Можно ли мы переопределить метод toString() для Enum?

Да, конечно вы можете переопределить метод toString(), чтобы определить конкретный способ отображения вашего enum при вызове метода toString (при переводе enum в обычную строку, например, для вывод в консоль or логи).
public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;

   @Override
   public String toString() {
       return "Выбрана роль - " + super.toString();
   }
}
На этом на сегодня у меня всё, до следующей части!Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 6
Другие материалы серии:
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION