Как корректно обрабатывать корнер кейсы, например пустую строку
Что проверяют
Как вы думаете о входных данных до того, как пишете основной алгоритм. На лайвкодинге это видно по тому, проговорили ли вы граничные случаи вслух до кода. Следом просят перечислить остальные крайние случаи задачи и показать, как вы их протестируете.
Как отвечать
Сначала договоритесь о контракте, потом проверяйте:
- null, пустая и пробельная строка это разное:
isEmpty()проверяет длину 0,isBlank()(с Java 11) ещё и строку из одних пробельных символов. Для" "первый вернётfalse, второйtrue; - решение о пустом входе: вернуть пустой результат,
0,Optional.empty()или броситьIllegalArgumentException. Наnullв публичном API принято падать сразу:Objects.requireNonNull(s, "s"). Главное, чтобы поведение было задокументировано и одинаково во всём классе; - ранний выход: guard clause в начале метода, дальше основной код без вложенных
if; - другие крайние случаи: один символ, строка из одинаковых символов, очень длинная строка, символы за пределами BMP.
length()считает единицы UTF-16, эмодзи занимает дваchar, и разворот черезcharAtразрывает суррогатную пару, а черезcodePoints()нет; - тесты: в JUnit 5
@ParameterizedTestс@NullAndEmptySourceи@ValueSource(strings = {" ", "\t"})закрывают пачку случаев одним тестом.
Хороший приём: до кода выпишите список входов (null, "", " ", "a", обычный пример) и потом прогоните по решению каждый.
Где спотыкаются
Пишут if (s == ""). Это сравнение ссылок, а не содержимого: для строки из ввода или собранной в рантайме условие будет ложным. Нужно isEmpty() или "".equals(s).
Вызывают s.isEmpty() раньше проверки на null и получают NullPointerException. Порядок s == null || s.isEmpty() важен из-за короткого замыкания.
Молча возвращают null на пустой вход. Проблема не решена, а перенесена в вызывающий код, где исключение вылетит далеко от причины.