Сьогодні я покажу вам прості прийоми, як уникнути NullPointerException у ваших додатках. Їм легко слідувати, але при цьому вони помітно підвищують надійність та якість вашого коду. Більш того, на мій досвід, одна перша порада вплине на якість вашого коду. Якщо ви знаєте якісь ще прийоми програмування Java, не соромтеся ділитися ними в коментарях.
Використовуйте
Існує безліч опенсорсних бібліотек, які беруть на собі важкий тягар перевірки Намагайтеся не повертати
Це ще одна хороша порада з програмування на Java, яку Джошуа Блох описує у своїй книзі "Java. Ефективне програмування". Повертаючи порожні колекції чи масиви, переконайтеся, що під час виклику базових методів начебто
Викликайте методи equals() та equalsIgnoreCase() у відомого рядка літералу, а не у невідомого об'єкта
Завжди викликайте методequals()
у відомого рядка, про який ви знаєте, що він не null
. Метод equals()
симетричний, тобто виклик a.equals(b)
і b.equals(a)
дасть однаковий результат (якщо a
й b
не null
), і з цієї причини багато програмістів не приділяють уваги тому, у яких об'єктів викликається equals()
, a
або b
. Одним з побічних ефектів цього стає NullPointerException, якщо метод викликається у null
.
Object unknownObject = null;
//плохой способ - может вызвать NullPointerException
if(unknownObject.equals("knownObject")){
System.err.println("This may result in NullPointerException if unknownObject is null");
}
//правильный способ - исключение NullPointerException не возникнет, даже если unknownObject null
if("knownObject".equals(unknownObject)){
System.err.println("better coding avoided NullPointerException");
}
Це була найпростіша порада, як уникнути NullPointerException, але вона одна призводить до величезних поліпшень, оскільки метод equals()
зустрічається повсюдно.
Вибирайте valueOf(), а не toString(), у випадках, коли обидва дають один результат
Оскільки викликtoString()
у посилання зі значенням null
викликає виняток NullPointerException, краще використовувати виклик valueOf()
, коли ми можемо отримати той самий результат, оскільки виклик valueOf()
від null
повернення null
. Особливо це стосується класів обгорток, таких як Integer
, Float
, Double
або BigDecimal
.
BigDecimal bd = getPrice();
System.out.println(String.valueOf(bd)); //не выбрасывает NPE
System.out.println(bd.toString()); //выбрасывает "Exception in thread "main" java.lang.NullPointerException"
Використовуйте ці поради, коли не впевнені, чи може об'єкт бути null
чи ні.
Використовуйте null
безпечні методи та бібліотеки
Існує безліч опенсорсних бібліотек, які беруть на собі важкий тягар перевірки null
. Одна з найпоширеніших – StringUtils
від Apache Commons. Використовуючи такі методи як StringUtils.isBlank()
, isNumeric()
, isWhiteSpace()
і т.д. Ви можете не турбуватися про виникнення NullPointerException.
//Методы StringUtils являются null-безопасными, они не вызовут NullPointerException
System.out.println(StringUtils.isEmpty(null));
System.out.println(StringUtils.isBlank(null));
System.out.println(StringUtils.isNumeric(null));
System.out.println(StringUtils.isAllUpperCase(null));
Висновок: true true false false І все ж таки перед використанням, не забудьте прочитати документацію null
-безпечних методів і класів. Це ще один із найкращих Java прийомів, який, не вимагаючи значних зусиль, веде до величезних покращень.
Намагайтеся не повертати null
з методу, краще поверніть порожню колекцію
Це ще одна хороша порада з програмування на Java, яку Джошуа Блох описує у своїй книзі "Java. Ефективне програмування". Повертаючи порожні колекції чи масиви, переконайтеся, що під час виклику базових методів начебто size()
чи length()
виникне NullPointerException. У класі Collections
спеціально оголошено зручні реалізації порожніх списків, множин і словників: Collections.EMPTY_LIST
, Collections.EMPTY_SET
and Collections.EMPTY_MAP
. Наприклад:
public List getOrders(Customer customer){
List result = Collections.EMPTY_LIST;
return result;
}
Аналогічно можна використовувати Collections.EMPTY_SET
замість Collections.EMPTY_MAP
того, щоб повертати null
.
Використовуйте анотації @NotNull та @Nullable
В описі ваших методів ви можете визначити угодуnull
-безпеки методів, використовуючи анотації @NotNull
і @Nullable щоб показати може метод повертати null
чи ні. Сучасні компілятори та IDE можуть використовувати ці анотації для аналізи вашого коду та видавати відповідні поради, наприклад, про пропущену перевірку на null
, або навпаки, про можливість прибрати зайву перевірку, що засмічує код. Такі інструкції, наприклад, підтримують IntelliJ IDE і FindBugs, крім цього вони входять до JSR 305. Але навіть якщо ваша IDE і не підтримує такі інструкції, вони самі по собі будуть гарною документацією. Дивлячись на @NotNull
програмісту @Nullable
буде простіше зрозуміти де потрібно додавати перевірку наnull
, А де - ні. Це, до речі, досить нова серед програмістів Java практика, і має пройти час, щоб вона поширилася.
Уникайте непотрібного автоупаковки та авторозпакування у вашому коді
Мало того, що це веде до створення зайвих часових об'єктів, автоупаковка ще може викликати NullPointerException, якщо клас обгортки -null
. Наприклад, наступний код "звалиться" в NullPointerException, якщо запис про людину не містить телефону і повертає null
.
Person ram = new Person("ram");
int phone = ram.getPhone();
При використанні автоупаковки або автораспаковування не тільки рівності, але й нерівності <
, >
можуть призводити до NullPointerException.
Дотримуйтесь угод і визначайте розумні значення за замовчуванням.
Один з найкращих способів уникнути NullPointerException в Java - правильне оголошення угод про кодування та дотримання їх. Більшість винятків NullPointerException виникають тоді, коли об'єкт намагаються створити, не володіючи всіма необхідними йому даними та залежностями. Заборонивши створення незавершених об'єктів, витончено відхиляючи подібні запити, ви позбавите себе у майбутньому великої кількості NullPointerException. Аналогічно, якщо ви дозволяєте створення об'єкта, то ви повинні підібрати розумне значення за замовчуванням. Наприклад, об'єкт класуEmployee
не може бути створений без імені та id
, але може не мати номер телефону. У такому разі в об'єктів Employee
, позбавлених номера, замістьnull
може повертатися нуль. Хоча подібна поведінка об'єкта варто заздалегідь продумати - можливо, що простіше буде перевірити на null
, ніж дзвонити за неіснуючим номером. У такому разі наявність додаткових умов на те, які поля null
, а які ні, допоможе ухвалити правильне рішення. Загалом вибір між негайним падінням програми чи присвоєнням null
— це важливе рішення у проектуванні, і зробивши вибір, ви повинні йому послідовно дотримуватися.
Задавайте обмеження на рівні СУБД
Використовуючи базу даних для зберігання об'єктів вашої програми, таких як покупці (Customers) або замовлення (Orders), буде розумно встановити "null
-овість" ваших об'єктів на рівні СУБД, за допомогою відповідних обмежень на таблиці. Бази даних часто містять інформацію з різних джерел і введення перевірок на пропущені значення підвищить цілісність ваших даних. Крім цього наявність перевірок на null на рівні СУБД, зменшить їх у вашому Java коді: завантажуючи дані з БД в Java-об'єкти, ви можете бути впевнені в їх наявності та прибрати зайві коди програми != null
.
Використовуйте шаблон Null-об'єкта
Створення спеціальнихNull
об'єктів - ще один спосіб уникнути NullPointerExcpetion в Java. Припустимо, якийсь метод у нашому додатку повертає об'єкт, з яким згодом працює програма, викликаючи його методи. Наприклад, метод Collection.iterator()
повертає об'єкт класу Iterator
, який використовується для проходу колекції. Тоді якщо у початкового об'єкта немає ніякого ітератора, натомість null
можна повернути спеціальний Null
об'єкт, у якого є метод hasNext()
, який завжди повертає.false
. Ось і все дорогий читач, на цьому я закінчую свої поради щодо позбавлення Java програм від помилок NullPointerException. Ви оціните, наскільки можуть бути корисні ці прості та не обтяжливі правила. Нагадую, що якщо ви хочете поділитися якимись ще прийомами NullPointerException в програмах на Java, не соромтеся робити це в коментарях. Перекладено спеціально для студентів JavaRush. Оригінал
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ