Что такое пул строк java
Перейти к содержимому

Что такое пул строк java

  • автор:

String Pool в Java

Java даёт выбор между примитивными типами данных и объектными. Одни передаются по значению, другие по ссылке. Одни занимают предсказуемое количество памяти, другие не очень (конечно только если Вы не знаете размеры метаинформации класса, для которого хотите произвести расчёт). Под одних память выделяется на стеке, под другие в heap’е. Они сильно отличаются друг от друга

Элементы в пределах своего типа (примитивный или объектный) ведут себя похоже, независимо от конкретного типа данных. Значения int ведут себя так же, как и значения типа short. В объектных типах данных схожая ситуация. Но есть исключения. Например — объектный тип String.

Что такое String?

String — это класс в Java, то есть объектный тип. Он описывает строки и хранит их данные в массиве char.

Оговорка:
Тип char используется в старых версиях Java, например 8-ой. В Java 11 используется уже массив byte’ов.

Сколько памяти занимает String? Примитивный тип char в Java имеет размер 2 byte’а. То есть один символ занимает в памяти 2 байта. Теперь представьте — каждый раз когда мы используем строку в Java, будь-то имя пользователя или ссылку на какой-либо сайт, мы создаём в системе большой массив char. Это занимает память. В объектных типах помимо всех ссылок на объекты и примитивов, память занимает ещё и заголовочная информация класса.

Зачем это знать? Строки — самый популярный тип данных в Java. Огромное количество данных описывается строками. Ещё более интересн тот факт, что строки в одних и тех же программах часто повторяются.

String — это immutable тип. То есть, после создания объекта этого типа поменять его значение нельзя. Отсюда делаем вывод — смысла в создании новых объектов типа String со значениями, для которых объекты уже были созданы — нет. Это не целесообразно, потому что каждый раз выделять память под одно и тоже, что ещё и не возможно изменить — чревато чрезмерным потреблением памяти.

Создатели Java заранее позаботились об этой проблеме и сделали тип String не совсем обычным объектным типом.

Что такое строковый пул?

Строковый пул или String pool — это особое место в heap’е, куда попадают объекты типа String после их создания. Он выполняет функцию кеша строк. Каждый раз, когда Вы создаёте строку, она попадает в строковый пул. Если же на момент создания новой строки пул уже содержит такое же значение, то вместо создания нового объекта возвращается тот, что уже лежит в пуле.

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

Как работать со строковым пулом?

Разберёмся с тем как работает String pool на практике.

Обычно строки в Java программах объявляются так:

String text = “Hello World”;

Что происходит в JVM за кадром? Остановитесь и подумайте. Если Вашим ответом будет что-то вроде — «В heap’е будет выделена память под строковый объект и ссылка на него будет возвращена и присвоена локальной переменной text» — Вы правы.

String text = “Hello World”;
String text2 = “Hello World”;

А что произойдёт тут? Если Вы думаете, что на обе локальные переменные будет выделена память в heap’е — Вы ошибаетесь. Именно в этом примере и видно результат работы пула строк.

В Java все строки, объявленные в виде литералов, то есть так:

“My String”

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

Как убедиться в том, действительно ли обе переменные указывают на один и тот же объект? Очень просто. Достаточно посмотреть что будет выведено в результате следующей операции:

System.out.println(text == text2);

Не спешите набирать код, я Вам подскажу — ответом будет `true`. Это означает — обе переменные указывают на один и тот же объект.

А как тогда сделать так, чтобы строки в пул не попадали? Это тоже сделать просто. Используйте конструктор явно при создании строк. Вот так:

String text = new String(“text”);

В этом случае, объект типа String будет создан, память под него будет выделена в heap’е, но в строковый пул он не попадёт. Это легко проверяется следующим примером:

String text = “Hello World”;
String text2 = new String(“Hello World”);
System.out.println(text == text2);

Результатом работы кода выше будет `false`, потому что теперь ссылки указывают на два разных объекта.

Ну и наконец, как добавить строку в строковый пул после её создания? Для этого класс String содержит метод под названием `intern()`. Именно он отвечает за сохранение текущего объекта String в пул строк. Пример использования:

String text = “Hello World”;
String text2 = new String(“Hello World”);
System.out.println(text == text2); // выведет false
text2 = text2.intern(); // попытается положить текущую строку в пул строк, обнаружит что такое значение уже там есть и вернёт объект из строкового пула. То есть тот, на который указывает переменная text
System.out.println(text == text2); // выведет true

Зачем знать о строковом пуле?

Строковый пул несёт не только пользу. Если не знать о его существовании и принципах работы, можно легко получить дыру в безопасности приложения. Сделать это довольно просто — достаточно добавить в пул какой-нибудь пароль или логин. Содержимое строкового пула доступно в memory dump’ах, к которым Вы или кто-то другой может получить доступ.

Надеюсь эта статья поможет Вам писать код более осознанно, ведь, теперь Вы знаете, что за строками в Java стоит String pool.

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7

Java-университет

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 1

Hey everyone! Программирование полно подводных камней. И нет практически ни одной темы, в которой вы не споткнетесь и не набьете шишки. Особенно это касается новичков. Уменьшить количество этого можно лишь одним способом — учиться. В частности это касается подробных разборов самых базовых тем. Сегодня продолжаю разбор вопросов 250+ с собеседований на Java-разработчика, которые хорошо охватывают базовые темы. Отмечу, что в списке есть и не совсем стандартные вопросы, позволяющие взглянуть на обычные темы под другим углом.

62. Что такое строковый пул и зачем он нужен?

В памяти в Java (Heap, о которой мы ещё поговорим) есть область — String pool , или строковый пул. Она предназначена для хранения строковых значений. Другими словами когда вы создаете некую строку, например через двойные кавычки:

 String str = "Hello world"; 

происходит проверка того, имеет ли строковой пул данное значение. Если имеет, переменной str присваивается ссылка на это значение в пуле. Если же не имеет, создастся новое значение в пуле, и ссылка на него будет присвоена переменной str . Рассмотрим пример:

 String firstStr = "Hello world"; String secondStr = "Hello world"; System.out.println(firstStr == secondStr); 

На экран будет выведено true . Мы помним, что == сравнивает именно ссылки — значит эти две ссылки ссылаются на одно и то же значение из строкового пула. Это сделано для того, чтобы не плодить множество одинаковых объектов типа String в памяти, ведь как мы помним, String — неизменяемый класс, и если у нас будет множество ссылок на одно и то же значение, плохого в этом ничего нет. Теперь невозможна ситуация, при которой изменение значения в одном месте приводит к изменениям сразу для нескольких других ссылок. Но тем не менее, если мы создадим строку через new :

 String str = new String("Hello world"); 

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

 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); 

Мы получим два false , и это значит, что у нас тут три разные значения, на которые ссылаются ссылки. Собственно, поэтому рекомендуется создавать строки просто через двойные кавычки. Тем не менее, можно сложить (или получать ссылку) значения в строковой пул и при создании объекта через new . Для этого используем метод класса строки — intern() . Данный метод принудительно создает значение в строковом пуле, ну или получает ссылку на него, если оно уже хранится там. Вот пример:

 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); 

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 2

в результате мы получим в консоли три значения true , а значит, все три переменные ссылаются на одну и ту же строку.

63. Какие GOF-шаблоны применяются в строковом пуле?

В строковом пуле явно прослеживается GOF шаблон — легковес (flyweight), иначе его называют поселенец. Если же вы увидели тут ещё какой-то шаблон — делитесь в комментарии. Ну а мы поговорим о шаблоне легковесе. Легковес — структурный шаблон проектирования, при котором объект, представляющий себя как уникальный экземпляр в разных местах программы, по факту не является таковым. Легковес экономит память, разделяя общее состояние объектов между собой, вместо хранения одинаковых данных в каждом объекте. Для понимания сути рассмотрим самый простой пример. Предположим, у нас есть интерфейс сотрудника:

 public interface Employee

И есть некоторые реализации, например, юрист:

 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("Ведение бухгалтерского отчёта. "); >> 

Методы весьма условны: нам всего лишь нужно видеть, что они выполняются. Такая же ситуация и с конструктором. Благодаря выводу в консоли мы будем видеть, когда создаются новые объекты. Также у нас есть отдел сотрудников, задача которого — выдавать запрашиваемого сотрудника, если же его нет — нанимать в штат и выдавать в ответ на запрос:

 public class StaffDepartment < private MapcurrentEmployees = 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; > > 

То есть логика простая: если есть данная единица — верни её, если нет — создай, помести в хранилище (что-то вроде кеша) и отдай назад. А теперь давайте посмотрим, как это всё работает:

 public static void main(String[] args) throws Exception

И в консоли, соответственно, будет вывод:

Юрист взят в штат. Решение юридических вопросов. Бухгалтер взят в штат. Ведение бухгалтерского отчёта. Решение юридических вопросов. Ведение бухгалтерского отчёта. Решение юридических вопросов. Ведение бухгалтерского отчёта. Решение юридических вопросов. Ведение бухгалтерского отчёта. Решение юридических вопросов. Ведение бухгалтерского отчёта.

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 3

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

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

Очевидно, что в данном вопросе речь идёт о методе 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)

В консоль будет выведено:
Hello, world it’s Amigo!

То есть, наше строковое значение было разбито на массив строк и разделителем послужил пробел (для разделения можно было использовать и не регулярное выражение пробела «\\s» и просто строковое выражение » » ). Второй, перегруженный метод имеет дополнительный аргумент — limit . limit — максимально допустимое значение получаемого массива. То есть, когда строка будет уже разбита на предельное допустимое количество подстрок, дальнейшей разбивки не будет, и у последнего элемента будет “остаток” от возможно недоразбитой строки. Пример:

 String str = "Hello, world it's Amigo!"; String[] arr = str.split(" ", 2); for (String s : arr)

Вывод в консоли:
Hello, world it’s Amigo!

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 4

Как мы видим, если бы не ограничение limit = 2 , последний элемент массива можно было бы разбить на три подстроки.

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

Причин для предпочтения массива строке при сохранении пароля несколько: 1. Строковой пул и неизменяемость строк. При использовании массива ( char[] ) мы можем явно стереть данные после того, как закончили работу с ним. Также мы можем сколько угодно переписывать массив, и действительного пароля нигде не будет в системе, даже до сбора мусора (достаточно изменить пару ячеек на недействительные значения). В то самое время String — immutable класс. То есть, если мы хотим изменить его значение, мы получим новое, а старое при этом останется в строковом пуле. Если мы захотим удалить String значение пароля, это может быть весьма сложным занятием, так как нужно, чтобы сборщик мусора удалил именно значение из String pool -а, и существует большая вероятность, что это String значение останется там надолго. То есть, в данной ситуации String уступает массиву char в безопасности хранения данных. 2. При случайном выводе в консоли (или в логи) значения String выведется само значение:

 String password = "password"; System.out.println("Пароль - " + password); 

Вывод в консоли:
Пароль — password
В то же время, если случайно вывести в консоль массив:

 char[] arr = new char[]; System.out.println("Пароль - " + arr); 

в консоли будет непонятная абракадабра:
Пароль — [C@7f31245a

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 5

На самом деле не абракадабра, а: [C — имя класса — массив char , @ — разделитель, после которого — 7f31245a — шестнадцатеричный хешкод. 3. Официальный документ, руководство по архитектуре криптографии Java прямо указывает на хранение паролей в char[] вместо String : “Казалось бы, логично собрать и сохранить пароль в объекте типа java.lang.String . Однако здесь есть предостережение: объекты типа String неизменяемы, т. е. Не определены методы, позволяющие изменять (перезаписывать) или обнулять содержимое объекта String после использования. Эта функция делает String объекты непригодными для хранения конфиденциальной информации, такой как пароли пользователей. Вместо этого вы всегда должны собирать и хранить конфиденциальную информацию о безопасности в массиве символов.”

Enum

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

Enum — перечисление, набор строковых констант, объединенных общим типом. Объявляется через ключевое слово — enum . Вот пример с enum — допустимые роли в некоторой школе:

 public enum Role

Слова, написанные большими буквами, и есть те самые константы перечисления, которые объявляются упрощенно, без использования оператора new . Использование перечислений заметно упрощает жизнь, так как они помогают избежать ошибок и путаницы в наименованиях (так как может быть только определенный перечень значений). Лично для меня они очень удобны при использовании в логической конструкции Switch.

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

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

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

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

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

Как по мне, вопрос немного странный, ну или я его не до конца понял. У меня есть две интерпретации: 1. Может ли быть enum без значений — да, конечно, это будет что-то вроде пустого класса — бессмысленно:

 public enum Role
 var s = Role.values(); System.out.println(s); 

Мы получим в консоли:
[Lflyweight.Role;@9f70c54

(пустой массив значений Role ) 2. Можно ли создать enum без оператора new — да, конечно. Как я выше уже сказал, для значений (перечислений) enum не нужно использовать оператор new , так как это — статические значения.

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

Да, конечно вы можете переопределить метод toString() , чтобы определить конкретный способ отображения вашего enum при вызове метода toString (при переводе enum в обычную строку, например, для вывод в консоль или логи).

 public enum Role < STUDENT, TEACHER, DIRECTOR, SECURITY_GUARD; @Override public String toString() < return "Выбрана роль - " + super.toString(); >> 

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 7 - 6

На этом на сегодня у меня всё, до следующей части!

  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 1
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 2
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 3
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 4
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 5
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 6
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 9
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 10
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 11
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 12
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 13
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 14
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 15
  • Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 16

Что такое пул строк в Java?

Что такое пул строк в Java?

Пул строк (String Pool) — это множество строк в кучи (Java Heap Memory). Мы знаем, что String — особый класс в java, с помощью которого мы можем создавать строковые объекты.

На диаграмме ниже мы видим как именно строковый пул расположен в памяти Java Heap. И как разные способы создания строк влияют на расположение их в памяти.

String Pool Java Javadevblog.com

Сам строковый пул возможен только потому, что строки в Java неизменные. Также пул строк позволяет сохранить память в Java Runtime, хотя это и требует больше времени на создание самой строки.

Пример работы с пулом строк

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

Однако использование оператора new заставляет класс String создать новый объект String. После этого можем использовать метод intern() , чтобы поместить этот объект в пул строк или обратиться к другому объекту из пула строк, который имеет такое же значение.

Ниже приведена программа, которая демонстрирует работу с пулом строк:

Java String. Вопросы к собеседованию и ответы на них, ч.2

Java-университет

Java String. Вопросы к собеседованию и ответы на них, ч.2 - 1

К сожалению статья не поместилась одним фрагментом, пришлось разбить её на две части. Начало смотрите тут

12. Напишите функцию для нахождения самого длинного палиндрома в данной строке

Строка может содержать в себе строки-палиндромы, и нахождение самого длинного палиндрома – это вопрос программирования. Ключевым моментом здесь является то, что из середины любого палиндрома, если мы пойдем направо и налево на 1 символ, это всегда будет одинаковый символ. К примеру, 12321, середина тут 3, и если мы продолжим движение с текущей позиции в обе стороны, мы получим 2, а затем 1. Мы используем подобную логику в нашей Java программе для нахождения самого длинного палиндрома. Однако если длина палиндрома четная, длина середины тоже четная, так что мы должны убедиться, что в нашей программе это так же предусмотрено, к примеру, 12333321, тут середина 33, и если мы продолжим движение в обе стороны, мы получим 3, 2 и 1. В нашей программе мы проходим по полученной строке с серединой на первом месте и проверяем левый и правый символ. Так же мы имеем две глобальные переменные для хранения начальной позиции палиндрома. Нам также необходимо проверить наличие уже найденного более длинного палиндрома, так как мы можем найти несколько палиндромов в данной строке. Ниже приведен пример программы, которая отлично работает во всех случаях. Мы можем усовершенствовать приведенный код, переместив цикл while в отдельный метод, но я оставил эту часть для вас . Пожалуйста, дайте мне знать, если у вас есть более удачная реализация, или программа не срабатывает в каком-то случае.

 package com.journaldev.util; public class LongestPalindromeFinder < public static void main(String[] args) < System.out.println(longestPalindromeString("1234")); System.out.println(longestPalindromeString("12321")); System.out.println(longestPalindromeString("9912321456")); System.out.println(longestPalindromeString("9912333321456")); System.out.println(longestPalindromeString("12145445499")); >public static String longestPalindromeString(String in) < char[] input = in.toCharArray(); int longestPalindromeStart = 0; int longestPalindromeEnd = 0; for (int mid = 0; mid < input.length; mid++) < // для случая нечетного палиндрома как 12321, 3 будет серединой int left = mid-1; int right = mid+1; // нам необходимо двигаться влево и вправо на 1 позицию до конца while (left >= 0 && right < input.length) < // ниже проверка, является ли это палиндромом if (input[left] == input[right]) < // обновление глобальных позиций, только если палиндром длиннее имеющегося if (right - left >longestPalindromeEnd - longestPalindromeStart) < longestPalindromeStart = left; longestPalindromeEnd = right; >> left--; right++; > // для четного палиндрома у нас должна быть подобная логика с размером середины 2 // для этого мы начнем на одну позицию правее left = mid-1; right = mid + 2;// к примеру, для 12333321 мы выбрали 33 в качестве середины while (left >= 0 && right < input.length) < if (input[left] == input[right]) < if (right - left >longestPalindromeEnd - longestPalindromeStart) < longestPalindromeStart = left; longestPalindromeEnd = right; >> left--; right++; > > // теперь у нас есть позиции для самого длинного палиндрома return in.substring(longestPalindromeStart, longestPalindromeEnd + 1); > > 

Программа выведет следующее:

 1 12321 12321 12333321 454454 

13. Какие различия между String, StringBuffer и StringBuilder

Строка является неизменной и финализированной в Java, поэтому все наши манипуляции со строкой всегда будут создавать новую строку. Манипуляции со строками ресурсоемкие, поэтому Java обеспечивает два полезных класса для манипуляций со строками – StringBuffer и StringBuilder . StringBuffer и StringBuilder являются изменяемыми классами. Операции с StringBuffer потокобезопасны и синхронизированы, а методы StringBuilder не потокобезопасны. Поэтому когда несколько нитей работают с одной строкой, мы должны использовать StringBuffer , но в однопоточном окужении мы должны использовать StringBuilder . StringBuilder более производительный, чем StringBuffer , поскольку не обременен синронизацией.

14. Почему строка неизменная и финализированная в Java

  1. Строковый пул возможен только потому, что строка неизменна в Java, таким образом виртуальная машина сохраняет много места в памяти (heap space), поскольку разные строковые переменные указывают на одну переменную в пуле. Если бы строка не была неизмененяемой, тогда бы интернирование строк не было бы возможным, потому что если какая-либо переменная изменит значение, это отразится также и на остальных переменных, ссылающихся на эту строку.
  2. Если строка будет изменяемой, тогда это станет серьезной угрозой безопасности приложения. Например, имя пользователя базы данных и пароль передаются строкой для получения соединения с базой данных и в программировании сокетов реквизиты хоста и порта передаются строкой. Так как строка неизменяемая, её значение не может быть изменено, в противном случае любой хакер может изменить значение ссылки и вызвать проблемы в безопасности приложения.
  3. Так как строка неизменная, она безопасна для много поточности и один экземпляр строки может быть совместно использован различными нитями. Это позволяет избежать синхронизации для потокобезопасности, строки полностью потокобезопасны.
  4. Строки используются в Java classloader и неизменность обеспечивает правильность загрузки класса при помощи Classloader . К примеру, задумайтесь об экземпляре класса, когда вы пытаетесь загрузить java.sql.Connection класс, но значение ссылки изменено на myhacked.Connection класс, который может осуществить нежелательные вещи с вашей базой данных.
  5. Поскольку строка неизменная, её hashcode кэшируется в момент создания и нет необходимости рассчитывать его снова. Это делает строку отличным кандидатом для ключа в Map и его обработка будет быстрее, чем других ключей HashMap . Это причина, почему строка наиболее часто используемый объект, используемый в качестве ключа HashMap .

15. Как разделить строку на части?

Мы можем использовать метод split(String regex) для разделения строки на массив строк, используя в качестве разделителя регулярное выражение.

 import java.util.Arrays; public class JavaSplitString < public static void main(String[] args) < String line = "I am a java developer"; String[] words = line.split(" "); String[] twoWords = line.split(" ", 2); System.out.println("String split with delimiter: "+Arrays.toString(words)); System.out.println("String split into two: "+Arrays.toString(twoWords)); //split string delimited with special characters String wordsWithNumbers = "I|am|a|java|developer"; String[] numbers = wordsWithNumbers.split("\\|"); System.out.println("String split with special character: "+Arrays.toString(numbers)); >> 

Метод split(String regex, int numOfStrings) является перегруженным методом для разделения строки на заданное количество строк. Мы можем использовать обратную черту для использования специальных символов регулярных выражений в качестве обычных символов. Программа выведет следующее:

 String split with delimiter: [I, am, a, java, developer] String split into two: [I, am a java developer] String split with special character: [I, am, a, java, developer] 

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

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

17. Как вы проверите две строки на подобность в Java?

Есть два способа проверить, являются ли две строки эквивалентными – используя оператор “ == ”, или используя метод equals . Когда мы используем оператор “ == ”, он проверяет значение строки, как ссылки, но в программировании большую часть времени мы проверяем эквивалентность строки только для значения. Поэтому мы должны использовать метод equals для проверки двух строк на эквивалентность. Еще есть метод equalsIgnoreCase , который мы можем использовать для игнорирования регистра.

 String s1 = "abc"; String s2 = "abc"; String s3= new String("abc"); System.out.println("s1 == s2 ? "+(s1==s2)); //true System.out.println("s1 == s3 ? "+(s1==s3)); //false System.out.println("s1 equals s3 ? "+(s1.equals(s3))); //true 

18. Что такое пул строк?

Java String. Вопросы к собеседованию и ответы на них, ч.2 - 2

Как подсказывает название, пул строк – это набор строк, который хранится в памяти Java heap. Мы знаем, что String это специальный класс в Java, и мы можем создавать объекты этого класса, используя оператор new точно так же, как и создавать объекты, предоставляя значение строки в двойных кавычках. Диаграмма ниже объясняет, как пул строк размещается в памяти Java heap и что происходит, когда мы используем различные способы создания строк. Пул строк возможен исключительно благодаря неизменяемости строк в Java и реализации идеи интернирования строк. Пул строк также является примером паттерна Приспособленец (Flyweight). Пул строк помогает экономить большой объем памяти, но с другой стороны создание строки занимает больше времени. Когда мы используем двойные кавычки для создания строки, сначала ищется строка в пуле с таким же значением, если находится, то просто возвращается ссылка, иначе создается новая строка в пуле, а затем возвращается ссылка. Тем не менее, когда мы используем оператор new, мы принуждаем класс String создать новый объект строки, а затем мы можем использовать метод intern() для того, чтобы поместить строку в пул, или получить из пула ссылку на другой объект String с таким же значением. Ниже приведен пример, показывающий работу пула строк.

 public class StringPool < public static void main(String[] args) < String s1 = "Cat"; String s2 = "Cat"; String s3 = new String("Cat"); System.out.println("s1 == s2 :"+(s1==s2)); System.out.println("s1 == s3 :"+(s1==s3)); >> 

Программа выведет следующее:

 s1 == s2 :true s1 == s3 :false 

19. Что делает метод intern()?

Когда метод intern() вызван, если пул строк уже содержит строку, эквивалентную к нашему объекту, что подтверждается методом equals(Object) , тогда возвращается ссылка на строку из пула. В противном случае объект строки добавляется в пул и ссылка на этот объект возвращается. Этот метод всегда возвращает строку, которая имеет то же значение, что что и текущая строка, но гарантирует что это будет строка из пула уникальных строк. Ниже приведен пример работы метода intern() :

 public class StringPool < public static void main(String[] args) < String a = "string a"; String b = new String("string a"); String c = b.intern(); System.out.println(a == b); System.out.println(b == c); System.out.println(a == c); >> Программа выведет следующее: false false true 

20. Являются ли строки потокобезопасными в Java?

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

21. Почему строка является популярным ключем в HashMap в Java?

Поскольку строки неизменны, их хэшкод кэшируется в момент создания, и не требует повторного пересчета. Это делает строки отличным кандидатом для ключа в Map и они обрабатываются быстрее, чем другие объекты-ключи HashMap . Вот почему строки преимущественно используются в качестве ключей HashMap . Надеюсь, что вопросы, перечисленные в этой статье помогут вам на собеседованиях, пожалуйста, дайте мне знать, если я что-то пропустил. Ссылка на оригинальную статью Автор: Pankaj Kumar

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *