Когда я только начинал учить Java, строки всегда вызывали больше всего вопросов. "Почему мой код не работает? Я же написал ==!". Поэтому я решил собрать топ-10 самых популярных вопросов про строки, с которыми сталкивается каждый начинающий джавист. Давай разберемся с ними раз и навсегда.10 самых задаваемых вопросов о строках в Java - 1

1. Как правильно сравнивать строки: == или equals()?

Начнем с классики. Запомни простое правило: "==" сравнивает адреса в памяти, а equals() сравнивает содержимое строк. Представь, что у тебя две одинаковые книги — это разные физические объекты (==), но содержание у них одно и то же (equals).

String str1 = new String("Java");
String str2 = new String("Java");

System.out.println(str1 == str2);        // false - разные объекты!
System.out.println(str1.equals(str2));   // true - содержимое одинаковое
Поэтому в 99% случаев тебе нужен именно equals(). А еще лучше — используй equalsIgnoreCase(), если регистр не важен. Кстати, есть классная штука — пул строк. Когда ты пишешь String s = "Java" без new, Java складывает такие строки в специальное хранилище, и тогда == может сработать. Но лучше не полагаться на это и всегда использовать equals() — так надежнее.

2. Почему char[] безопаснее String для паролей?

Когда мой друг устраивался на работу, на собеседовании его спросили: "Почему в правильных программах пароли хранят в char[], а не в String?" Ответ связан с тем, что строки неизменяемые. Создал строку с паролем — и она будет болтаться в памяти до тех пор, пока сборщик мусора не решит ее убрать. А это может быть через час, два, день. С массивом char[] все проще — ты можешь сам затереть пароль сразу после использования. Просто пройдись по массиву и забей все нулями или любыми другими символами. Пароль исчез из памяти, и никакой злоумышленник его не достанет. Именно поэтому в классе JPasswordField метод getPassword() возвращает char[], а не String. Безопасность превыше всего!

char[] password = {'s', 'e', 'c', 'r', 'e', 't'};
// используем пароль...
// затираем данные
for (int i = 0; i < password.length; i++) {
    password[i] = '0';
}

3. Можно ли использовать строки в switch? (Спойлер: да!)

Помню, как один мой приятель спросил: "А можно в switch строки проверять?" Я ответил: "Конечно! Но только с Java 7". С тех пор прошло много лет, и теперь мы используем Java 21, где switch вообще стал мощным инструментом с pattern matching. Но начнем с основ. Да, строки в switch работают отлично с Java 7. Более того, в современной Java появился новый синтаксис switch-выражений (Java 14+), который делает код еще чище. Смотри, как круто:

// Старый стиль (Java 7+)
String day = "Monday";
switch (day) {
    case "Monday":
    case "Tuesday":
        System.out.println("Начало недели");
        break;
    case "Friday":
        System.out.println("Ура, пятница!");
        break;
}

// Новый стиль (Java 14+) - намного элегантнее!
String mood = switch (day) {
    case "Monday", "Tuesday" -> "Работаем";
    case "Friday" -> "Скоро выходные!";
    case "Saturday", "Sunday" -> "Отдыхаем";
    default -> "Обычный день";
};

4. Как преобразовать String в int (и обратно)?

Это вопрос задают в первую неделю обучения. Представь: пользователь вводит число, но Java получает строку. Что делать? Раньше я показывал Integer.parseInt() — и этого было достаточно. Сейчас есть куча способов, но основной остался тот же.

// String → int
String numberStr = "42";
int number = Integer.parseInt(numberStr);

// int → String
int age = 25;
String ageStr = String.valueOf(age);
// или проще:
String ageStr2 = "" + age;
Только будь осторожен с parseInt() — если строка содержит не число, словишь NumberFormatException. Поэтому лучше оборачивай в try-catch или проверяй заранее. А еще помни про Integer.valueOf() — он возвращает Integer (объект), а не примитив int. Для небольших чисел (-128 до 127) Java использует кэш, так что valueOf() может быть эффективнее.

5. Как разбить строку на части?

Когда работаешь с данными, постоянно нужно разбивать строки — по запятым, пробелам, табуляциям. Метод split() — твой лучший друг в таких ситуациях. Он принимает регулярное выражение и возвращает массив строк.

String text = "Java,Python,JavaScript,C++";
String[] languages = text.split(",");
// languages = ["Java", "Python", "JavaScript", "C++"]

// Разбить по любым пробельным символам
String sentence = "Привет    мир\tиз\nJava";
String[] words = sentence.split("\\s+");
// words = ["Привет", "мир", "из", "Java"]
Обрати внимание на "\\s+" — это регулярка, которая означает "один или больше пробельных символов" (пробелы, табы, переносы строк). Двойной слэш нужен, потому что в строке Java слэш — это escape-символ. А еще есть крутой метод lines() (с Java 11), который разбивает текст по строкам и возвращает Stream. Супер удобно для обработки больших текстов!

6. String, StringBuilder или StringBuffer — что выбрать?

Этот вопрос — классика собеседований. Объясню на простой аналогии: String — это книга в твердом переплете. Написали, напечатали — все, не изменишь. StringBuilder — это блокнот с карандашом: можно стирать и переписывать сколько угодно. String — неизменяемый. Каждая операция создает новый объект. Если конкатенируешь в цикле тысячу раз — получишь тысячу объектов в памяти. StringBuilder — изменяемый и быстрый, но не потокобезопасный. StringBuffer — это старый брат StringBuilder, появился еще в Java 1.0. Он синхронизированный (потокобезопасный), но медленнее. В 99% случаев используй StringBuilder.

// Плохо — создается куча промежуточных строк
String result = "";
for (int i = 0; i < 1000; i++) {
    result += i + " ";
}

// Хорошо — один объект, все изменения на месте
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i).append(" ");
}
String result = sb.toString();

7. Как повторить строку N раз?

Раньше приходилось писать цикл или использовать Apache Commons Lang с методом repeat(). Я и мои коллеги всегда смотрели на Python и завидовали: там можно просто "ab" * 5, и получится "ababababab". Но в Java 11 появился встроенный метод repeat(), и жизнь стала прекрасной!

String str = "Java";
String repeated = str.repeat(3);
System.out.println(repeated);  // JavaJavaJava

// Супер удобно для форматирования
String separator = "=".repeat(50);
System.out.println(separator);
System.out.println("Заголовок");
System.out.println(separator);
Никаких внешних библиотек, никаких циклов — просто и красиво. Это один из тех моментов, когда понимаешь, что Java действительно развивается и становится удобнее. До Java 11 можно было обойтись String.join("", Collections.nCopies(n, str)), но это же неочевидно и громоздко.

8. Как работать с датами в строках?

О, даты — это отдельная боль всех начинающих. Раньше приходилось мучиться с SimpleDateFormat и Date. Это была настоящая пытка: не потокобезопасно, неудобно, постоянно ловишь исключения. К счастью, в Java 8 появился пакет java.time — и все изменилось.

// Современный подход (Java 8+) — используй его!
String dateStr = "2024-12-03";
LocalDate date = LocalDate.parse(dateStr);
System.out.println(date);  // 2024-12-03

// Если формат не стандартный
String customDate = "03/12/2024";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate parsedDate = LocalDate.parse(customDate, formatter);

// Обратно в строку
String formatted = date.format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
System.out.println(formatted);  // 03 декабря 2024
LocalDate, LocalTime, LocalDateTime — это твои новые друзья. Забудь про Date и Calendar (если только не работаешь с древним легаси-кодом). Новый API потокобезопасный, неизменяемый и гораздо понятнее. А еще там есть куча удобных методов типа plusDays(), minusMonths(), isBefore(), isAfter() — красота!

9. Как посчитать вхождения символа в строке?

Этот вопрос часто встречается в задачках на собеседованиях. Раньше можно было использовать StringUtils.countMatches() из Apache Commons, но зачем тащить целую библиотеку ради одного метода? Напишем свое решение или используем Stream API.

String text = "Programming in Java is awesome!";

// Способ 1: классический цикл (понятно новичкам)
int count = 0;
for (char c : text.toCharArray()) {
    if (c == 'a') count++;
}

// Способ 2: через Stream API (элегантно, современно)
long count2 = text.chars()
                  .filter(ch -> ch == 'a')
                  .count();

// Способ 3: использовать replaceAll для подсчета подстрок
String phrase = "Java Java Java";
int javaCount = phrase.split("Java", -1).length - 1;
System.out.println("'Java' встречается " + javaCount + " раз");
Мне больше всего нравится вариант со Stream API — он компактный и показывает, что ты знаком с современными фичами Java. Но на собеседовании лучше сначала показать простой цикл (чтобы доказать, что понимаешь основы), а потом блеснуть Stream API как бонус.

10. Что еще полезного есть в современных строках?

С каждой новой версией Java строки становятся все удобнее. Вот несколько крутых методов, которые появились относительно недавно и которые я активно использую в своих проектах:

// Java 11: strip() — убирает пробелы лучше, чем trim()
String text = "  Hello World  ";
System.out.println(text.strip());      // "Hello World" (убирает Unicode пробелы)
System.out.println(text.stripLeading()); // "Hello World  "
System.out.println(text.stripTrailing()); // "  Hello World"

// Java 11: isBlank() — проверяет, что строка пустая или только пробелы
String empty = "   ";
System.out.println(empty.isBlank());    // true
System.out.println(empty.isEmpty());    // false (там же пробелы!)

// Java 11: lines() — разбивает по строкам и возвращает Stream
String multiline = "Строка 1\nСтрока 2\nСтрока 3";
multiline.lines()
         .forEach(System.out::println);

// Java 13+: Text Blocks — многострочные строки без мучений!
String html = """
    <html>
        <body>
            <h1>Hello, World!</h1>
        </body>
    </html>
    """;
Text Blocks — это просто находка! Раньше приходилось писать длинные строки с кучей \\n и конкатенацией. Теперь можно писать SQL-запросы, HTML, JSON прямо в коде, и они выглядят читаемо. А еще есть indent(), transform(), formatted() — куча полезных методов для работы со строками.

Вывод

Строки в Java — это не так просто, как кажется на первый взгляд. За годы обучения я заметил: кто хорошо разобрался со строками на старте, тот потом легче учит коллекции, обобщения и многопоточность. Потому что строки — это основа основ, с ними работаешь каждый день. Современная Java (17-21) сделала работу со строками намного приятнее: Text Blocks, новые методы вроде repeat() и isBlank(), улучшенный switch. Не бойся использовать новые фичи — они не просто так появились, они реально экономят время и делают код чище. И помни: практика важнее теории. Пиши код, экспериментируй, ломай — только так научишься программировать по-настоящему.