Почему String неизменяемый? и как это помогает программисту?
Что помимо того что нельзя наследоваться от final класса, а именно String.class , и того что при использовании метода concat() и операции + будет создан новый объект типа String а не изменен существующий, используется при определении неизменяемости класса String ? Как неизменяемость (immutable) класса String помогает в реальных ситуациях программисту. Были бы интересны примеры связанные с HashMap и многопоточностью.
Отслеживать
задан 13 июл 2016 в 10:36
1,996 5 5 золотых знаков 29 29 серебряных знаков 48 48 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вот тут человек уже ответил на ваш вопрос:
- вы можете передавать строку между потоками и не беспокоиться что она будет изменена
- нет проблем с синхронизацией (не нужно синхронизировать операции со String)
- отсутствие утечек памяти
- в Java строки используются для передачи параметров для авторизации, открытия файлов и т.д. — неизменяемость позволяет избежать проблем с доступом
- возможность кэшировать hash code
А если нужно изменять, есть StringBuffer.
Как реализована неизменность string в java
В Java строка ( String ) является неизменяемым ( immutable ) объектом, то есть после создания строки её нельзя изменить. Когда мы изменяем строку, мы фактически создаем новую строку, которая содержит изменения. Это означает, что операции над строками в Java обычно более безопасны, чем операции над изменяемыми объектами.
Неизменность строк в Java достигается путем хранения строк в виде массива символов ( char[] ), который является неизменяемым объектом. При изменении строки создается новый массив символов с новым значением строки.
Также Java использует кэширование строк, что позволяет экономить память. Если две строки содержат одинаковые символы, то они ссылаются на один и тот же объект в памяти (строка сохраняется в пуле строк). Это возможно благодаря тому, что строка является неизменяемой.
Почему строки в Java неизменные?
Сегодня мы поговорим о строках (Strings) в Java и разберем один очень важный вопрос, которой очень часто задают на собеседованиях, а именно: Почему строки в Java неизменны и финализированы?
Строка является одним из наиболее часто используемых классов в любом языке программирования. Как мы знаем, строка в Java является неизменной и финализированной, а Java Runtime поддерживает общий пулл строк, что делает его этот класс особенным.
Преимущества неизменности строк в Java
- Само существование пула строк возможно только потому, что строка в Java является неизменной. Поэтому Java Runtime экономит много места в общей кучи (java heap space). Дело в том, что различные переменные могут обращаться к одной и той же String-переменной в пуле. Если строка не была бы неизменной, то и интернирование такой строки не было бы возможно. Все потому, что любая переменная могла бы изменять значение этой строки и это сразу бы отражалось и в других переменных.
- Если строка не является неизменной, то это вызывает серьезную угрозу безопасности вашей программы. Например, для соединения с базой данных имя пользователя базы и пароль передаются в виде строк. Тоже самое и в программировании сокетов, где хост и порт передаются в виде обычных String. Именно поэтому значение строки не может быть изменено. В противном случае любой хакер или вредоносная программа может изменить значение строк и вызвать проблемы безопасности в вашей программе.
- Строки неизменны, а это значит, что они потокобезопасны. Это избавляет нас от использования синхронизаций во время работы в мультипоточной среде.
- Строки также используются в загрузчике классов Java и неизменность строк обеспечивает безопасность выполнения загрузки класса. Например, вы пытаетесь загрузить класс java.sql.Connection, но значение ссылки было изменено вредоносной программой. Это может привести к непредвиденным результатам и данным в вашей БД.
- Строки неизменны, а значит их хеш-коды кешируются во время создания и не нуждаются в еще одном вычислении. Это делает строки отличным кандидатом на использование в Map в качестве ключа (key) и будет работать быстрее объектов HashMap.
Вот и все аргументы в пользу неизменности строк в Java. Следите за обновлениями на Javadevblog.com
Java: Неизменяемость строк
Кажется, что ответом будет «HEXLET» , но это не так. Эта программа выведет «hexlet» (проверьте на tryjshell). Почему?
Дело в том, что строки в Java неизменяемы. Не существует способа и методов, способных изменить саму строку. Любой метод строки может только вернуть новую строку.
Основная причина, почему так сделано – производительность. Строки, и другие примитивные типы данных нельзя менять практически ни в одном современном языке.
Вторая причина связана с простотой кода. Когда мы не изменяем данные, а создаем новые данные на основе старых, то код проще анализировать и модифицировать. Особенно если с данными происходит много манипуляций, с этим вам еще предстоит столкнуться.
Но как же поступать, если данные нужно поменять? Для этого достаточно заменить значение переменной:
var language = "JAVA"; language = language.toLowerCase(); System.out.println(language); // => java
С другой стороны, именно в такой ситуации можно создать новую переменную с другим именем:
var language = "JAVA"; var processedLanguage = language.toLowerCase(); System.out.println(processedLanguage); // => java
Такой подход нередко предпочтительнее по соображениям читаемости. Переменные, которые постоянно меняются, сложнее анализировать. В итоге все зависит от задачи. С опытом придет понимание, какой подход лучше.
Задание
Данные, вводимые пользователями в формах, часто содержат лишние пробельные символы в конце или начале строки. Кроме того, пользователи могут вводить одно и то же в разном регистре, что потом мешает работе с данными. Поэтому перед тем как добавлять их, данные обрабатывают (говорят нормализуют). В базовую обработку входят два действия:
- Удаление концевых пробельных символов с помощью метода .trim() , например, было: » hexlet\n » , стало: «hexlet»
- Приведение к нижнему регистру с помощью метода toLowerCase() . Было: «SUPPORT@hexlet.io» , стало: «support@hexlet.io» .
Обновите переменную email записав в неё то же самое значение, но обработанное по схеме указанной выше. Распечатайте то, что получилось, на экран.
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
