Введение
В этом лабораторном занятии мы рассмотрим, как обрабатывать потенциальные значения null при работе с оберточным классом Character в Java. В отличие от примитивного типа char, объект Character может быть null, и если не обработать это, могут возникнуть ошибки NullPointerException. Мы научимся проверять, является ли объект Character равным null, комбинировать проверки на null с другими проверками свойств символов и использовать класс Optional для более безопасной обработки null значений.
С помощью практических примеров вы получите практический опыт написания надежного кода на Java, который эффективно управляет null объектами Character, предотвращая распространенные ошибки во время выполнения и повышая надежность ваших приложений.
Проверить обёртку Character на null
На этом этапе мы рассмотрим, как обрабатывать потенциальные значения null при работе с оберточным классом Character в Java. В то время как примитивные типы char не могут быть null, оберточный класс Character, являясь объектом, может быть таковым. Обработка значений null является важной частью программирования, чтобы избежать ошибок NullPointerException, которые часто встречаются в Java и могут привести к аварийному завершению программы.
Мы начнем с создания простой Java-программы, которая демонстрирует, как может возникнуть ошибка NullPointerException, когда вы пытаетесь вызвать метод для объекта Character, равного null.
Откройте файл
HelloJava.javaв редакторе WebIDE, если он еще не открыт.Замените все содержимое файла следующим кодом:
public class HelloJava { public static void main(String[] args) { Character myChar = null; // Эта строка вызовет ошибку NullPointerException, если myChar равно null // System.out.println("Is myChar a letter? " + Character.isLetter(myChar)); } }В этом коде:
- Мы объявляем переменную
Characterс именемmyCharи явно устанавливаем ее значение вnull. - Закомментированная строка
System.out.println("Is myChar a letter? " + Character.isLetter(myChar));пытается вызвать статический методCharacter.isLetter()с аргументомnull. ХотяCharacter.isLetter()является статическим методом, передача ему объектаCharacter, равногоnull, все равно приведет к ошибкеNullPointerException, так как метод внутренне пытается преобразовать объектCharacterв примитивный типchar, что невозможно дляnull.
- Мы объявляем переменную
Сохраните файл (Ctrl+S или Cmd+S).
Теперь скомпилируем программу. Откройте терминал внизу WebIDE и выполните следующую команду:
javac HelloJava.javaЕсли компиляция прошла успешно, вы не увидите никакого вывода.
Теперь попробуем запустить программу. В терминале выполните следующую команду:
java HelloJavaПоскольку строка, которая могла бы вызвать ошибку, закомментирована, программа запустится без вывода и ошибок. Это показывает, что просто объявление объекта
Characterкакnullне вызывает немедленной проблемы; проблема возникает, когда вы пытаетесь выполнять операции с ним.
На следующем этапе мы раскомментируем проблемную строку и увидим ошибку NullPointerException.
Совместить проверку на null и проверку на букву
На предыдущем этапе мы увидели, как может возникнуть ошибка NullPointerException при работе с объектами Character. Теперь раскомментируем строку, которая вызывает ошибку, и посмотрим, как проявляется исключение. Затем мы научимся распространенному способу предотвратить это, комбинируя проверку на null с проверкой на букву.
Откройте файл
HelloJava.javaв редакторе WebIDE.Раскомментируйте строку, которая вызывает метод
Character.isLetter(). Теперь ваш код должен выглядеть так:public class HelloJava { public static void main(String[] args) { Character myChar = null; // Эта строка вызовет ошибку NullPointerException, если myChar равно null System.out.println("Is myChar a letter? " + Character.isLetter(myChar)); } }Сохраните файл (Ctrl+S или Cmd+S).
Скомпилируйте модифицированную программу в терминале:
javac HelloJava.javaОпять же, если компиляция прошла успешно, вы не увидите никакого вывода.
Теперь запустите программу:
java HelloJavaВы должны увидеть вывод, похожий на следующий, который указывает на ошибку
NullPointerException:Exception in thread "main" java.lang.NullPointerException at java.base/java.lang.Character.isLetter(Character.java:xxxx) at HelloJava.main(HelloJava.java:x)Эта ошибка возникает потому, что
myCharравноnull, и методCharacter.isLetter()не может работать с объектом, равнымnull.Чтобы предотвратить эту ошибку
NullPointerException, мы можем добавить проверку, является лиmyCharравнымnullперед тем, как попытаться вызвать методCharacter.isLetter(). Для этого можно использовать операторif. Измените файлHelloJava.java, добавив такую проверку:public class HelloJava { public static void main(String[] args) { Character myChar = null; if (myChar != null && Character.isLetter(myChar)) { System.out.println("myChar is a letter."); } else { System.out.println("myChar is not a letter or is null."); } } }В этом обновленном коде:
- Мы используем оператор
ifс двумя условиями, объединенными оператором&&(логическое И). - Первое условие,
myChar != null, проверяет, не является лиmyCharравнымnull. - Второе условие,
Character.isLetter(myChar), проверяет, является лиmyCharбуквой. - Оператор
&&имеет "короткую цепочку". Это означает, что если первое условие (myChar != null) ложно, второе условие (Character.isLetter(myChar)) не вычисляется. Это предотвращает ошибкуNullPointerException, так как мы пытаемся вызвать методCharacter.isLetter()только в том случае, еслиmyCharне равноnull.
- Мы используем оператор
Сохраните файл.
Скомпилируйте программу еще раз:
javac HelloJava.javaЗапустите программу:
java HelloJavaНа этот раз программа должна запуститься без ошибок и вывести:
myChar is not a letter or is null.Это происходит потому, что
myCharравноnull, поэтому первое условие в оператореif(myChar != null) ложно, и выполняется блокelse.
Подход, заключающийся в проверке на null перед доступом к методам или свойствам объекта, является фундаментальной техникой в Java для избежания ошибок NullPointerException.
Использовать Optional для безопасности при работе с null
На предыдущем этапе мы узнали, как предотвратить ошибку NullPointerException, явно проверяя, является ли объект null перед его использованием. Хотя этот подход эффективен, он иногда может привести к тому, что код будет перегружен проверками на null. В Java 8 был введен класс Optional как способ более функционального и выразительного управления потенциально null значениями.
Optional представляет собой контейнерный объект, который может содержать или не содержать не-null значение. Если значение присутствует, метод isPresent() возвращает true, а метод get() возвращает это значение. Если значение отсутствует, объект считается пустым, и метод isPresent() возвращает false. Вызов метода get() для пустого объекта Optional вызывает исключение NoSuchElementException.
Давайте перепишем наш пример, чтобы использовать Optional<Character> для обработки возможности null значения для объекта Character.
Откройте файл
HelloJava.javaв редакторе WebIDE.Замените все содержимое файла следующим кодом:
import java.util.Optional; public class HelloJava { public static void main(String[] args) { Character myChar = null; // По-прежнему может быть null // Создаем объект Optional из потенциально null объекта Character Optional<Character> optionalChar = Optional.ofNullable(myChar); // Используем методы Optional для проверки и обработки значения if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) { System.out.println("myChar is a letter."); } else { System.out.println("myChar is not a letter or is null."); } // Другой способ с использованием функциональных методов Optional (более продвинутый) // optionalChar.filter(Character::isLetter) // .ifPresentOrElse( // c -> System.out.println("myChar is a letter (using Optional methods)."), // () -> System.out.println("myChar is not a letter or is null (using Optional methods).") // ); } }В этом коде:
- Мы импортируем класс
Optional. - По-прежнему объявляем
myCharкак потенциальноnull. Optional<Character> optionalChar = Optional.ofNullable(myChar);создает объектOptional. МетодOptional.ofNullable()используется, когда значение может бытьnull. ЕслиmyCharравноnull,optionalCharбудет пустым объектомOptional. ЕслиmyCharимеет значение,optionalCharбудет содержать это значение.- Затем мы используем метод
optionalChar.isPresent()для проверки, содержит ли объектOptionalзначение, прежде чем пытаться получить его с помощьюoptionalChar.get()и передать в методCharacter.isLetter(). Это похоже на нашу предыдущую проверку наnull, но использует API классаOptional. - Закомментированная часть показывает более продвинутый способ использования
Optionalс функциональными методами, такими какfilterиifPresentOrElse, которые могут сделать код более компактным в определенных сценариях. В этом вводном уроке мы не будем фокусироваться на этом продвинутом использовании, но полезно знать о нем.
- Мы импортируем класс
Сохраните файл.
Скомпилируйте программу:
javac HelloJava.javaЗапустите программу:
java HelloJavaВывод должен быть таким же, как на предыдущем этапе:
myChar is not a letter or is null.Это подтверждает, что использование
Optional.ofNullable()иisPresent()корректно обрабатывает случайnull.
Теперь изменим myChar на не-null символ, чтобы посмотреть, как ведет себя программа.
Измените файл
HelloJava.java, установивmyCharравным символу, например, 'A':import java.util.Optional; public class HelloJava { public static void main(String[] args) { Character myChar = 'A'; // Теперь myChar имеет значение // Создаем объект Optional из потенциально null объекта Character Optional<Character> optionalChar = Optional.ofNullable(myChar); // Используем методы Optional для проверки и обработки значения if (optionalChar.isPresent() && Character.isLetter(optionalChar.get())) { System.out.println("myChar is a letter."); } else { System.out.println("myChar is not a letter or is null."); } } }Сохраните файл.
Скомпилируйте программу:
javac HelloJava.javaЗапустите программу:
java HelloJavaНа этот раз вывод должен быть следующим:
myChar is a letter.Это показывает, что когда
myCharимеет значение, методoptionalChar.isPresent()возвращаетtrue, и проверкаCharacter.isLetter()выполняется корректно.
Использование Optional может сделать ваш код более читаемым и явно указать, когда значение может отсутствовать, уменьшая вероятность неожиданных ошибок NullPointerException.
Резюме
В этом уроке мы научились обрабатывать потенциально null значения при работе с оберточным классом Character в Java. Мы начали с демонстрации того, как может возникнуть ошибка NullPointerException при попытке использовать метод для null объекта Character, даже для статических методов, таких как Character.isLetter(). Это показало важность явной проверки на null перед выполнением операций над объектами Character для предотвращения аварийного завершения программы.



