JavaRush /Java блог /Random UA /Прийоми та поради. Як уникнути NullPointerException у Jav...
DarthVictor
28 рівень

Прийоми та поради. Як уникнути NullPointerException у Java додатках

Стаття з групи Random UA
Прийоми та поради.  Як уникнути NullPointerException в Java додатках - 1Сьогодні я покажу вам прості прийоми, як уникнути NullPointerException у ваших додатках. Їм легко слідувати, але при цьому вони помітно підвищують надійність та якість вашого коду. Більш того, на мій досвід, одна перша порада вплине на якість вашого коду. Якщо ви знаєте якісь ще прийоми програмування Java, не соромтеся ділитися ними в коментарях. Прийоми та поради.  Як уникнути NullPointerException в Java додатках - 2

Викликайте методи 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_SETand 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. Оригінал
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ