Çəkinin! = Null

NullPointerException qarşısını almaq üçün object != null istifadə edin object != null .

Bunun üçün yaxşı bir alternativ varmı?

Məsələn:

 if (someobject != null) { someobject.doCalc(); } 

NullPointerException , obyektin null olub-olmaması məlum NullPointerException , bu qarşısını alır.

Xahiş edirik qəbul etdiyiniz cavabın köhnəlmiş ola biləcəyini, daha sonrakı bir yanaşma üçün on123.ru.site/questions/50 / ... ' a baxın.

3608
07 нояб. Goran Martinic tərəfindən təyin olunan 07 Nov. 2008-11-07 11:31 '08 at 11:31 2008-11-07 11:31
@ 60 cavab
  • 1
  • 2

Mənə gənc inkişafçılar bir nöqtədə qaçmaq məcburiyyətində olduqca ümumi bir problem kimi səslənir: onlar ya bilmirlər və ya iştirak etdikləri müqavilələrə güvənməzlər və müdafiə etmək üçün onları sıfırdan üstün hesablar. Bundan əlavə, öz kodunu yazarkən, zəngləri sıfırlamaq üçün tələb edən bir şeyi göstərmək üçün sıfırdan dönənlərə etibar edirlər.

Başqa sözlə, sıfır çek edildikdə iki hal var:

  • Null bir müqavilə baxımından etibarlı bir cavab olduqda; və

  • Bu yanlış bir cavabsa.

(2) asan. Təsdiq assert (təsdiqləmələrdən) istifadə edin və ya uğursuz (məsələn, NullPointerException ). İddialar çox az istifadə edilən Java funksiyasıdır, 1.4 əlavə olunur. Sintaksis:

 assert <condition> 

və ya

 assert <condition> : <object> 

burada <condition> məntiqi ifadədir və <object> bir obyektdir, toString() metodunun çıxışı səhv daxil edilir.

Vəziyyət doğru deyilsə, assert Error ( AssertionError ) çağırır. Varsayılan olaraq, Java iddiaları yox sayır. Siz -ea seçimini JVM- -ea keçərək təsdiqləməyə imkan yarada bilərsiniz. Fərdi siniflər və paketlər üçün fərziyyələri aktivləşdirə və aradan buraxa bilərsiniz. Bu, testin testin inkişaf və sınaqdan keçirilməsi ilə bağlı testlər vasitəsilə test edə biləcəyini və testlərinizin təsdiqi üzərində performans təsirinin olmaması ilə yanaşı göstərdiyini nəzərə alsaq, istehsal mühitində buraxa bilərsiniz.

Bu halda iddiaları istifadə etməli, OK, çünki kod yalnız uğursuz olacaq və bu, təsdiqləmələr istifadə edər. Yalnız fərqlər budur ki, əvvəllər baş verə biləcək ifadələrlə, daha mənalı şəkildə və ehtimal ki, gözlənilmədiyin bu səbəbin nə olduğunu başa düşməyinizə kömək edə biləcək əlavə məlumatlar ola bilər.

(1) bir az daha mürəkkəbdir. Çağırdığınız kod üzərində heç bir nəzarətiniz yoxdursa, sıxılmış vəziyyətdədir. Null etibarlı bir cavabsa, onu yoxlamaq lazımdır.

Əgər bu nəzarət etdiyiniz bir kod olsa (və bu tez-tez olur) bu başqa bir hekayəsidir. Bir cavab olaraq sıfırdan istifadə etməyin. Koleksiyonları geri qaytarma üsullarını istifadə etmək asandır: boş koleksiyonları (ya da diziler) hemen hemen her zaman sıfırdan döndürür.

Qeyri-kolleksiyalarla bu çətin ola bilər. Bunu bir nümunə olaraq düşünün: əgər bu interfeyslər varsa:

 public interface Action { void doSomething(); } public interface Parser { Action findAction(String userInput); } 

Parser xammal istifadəçi girişini alır və bir şey tapır, bəlkə bir şəkildə komanda xətti interfeysi tətbiq edərsə. Müvafiq fəaliyyət olmadıqda, indi müqavilə bağlaya bilərsiz. Bu, söhbət etdiyiniz sıfır yoxlamaya gətirib çıxarır.

Alternativ bir həll heç vaxt null qaytarılması və Null Obyekt şablonunu istifadə etməkdir :

 public class MyParser implements Parser { private static Action DO_NOTHING = new Action() { public void doSomething() {  } }; public Action findAction(String userInput) { // ... if (  ) { return DO_NOTHING; } } } 

Müqayisə üçün:

 Parser parser = ParserFactory.getParser(); if (parser == null) { // now what? // this would be an example of where null isn't (or shouldn't be) a valid response } Action action = parser.findAction(someInput); if (action == null) { // do nothing } else { action.doSomething(); } 

üçün

 ParserFactory.getParser().findAction(someInput).doSomething(); 

daha yaxşıdır, çünki daha sıxılmış koda səbəb olur.

Bununla belə, findAction () metodunun istisna bir mənalı səhv mesajı ilə atılmasına zərurət ola bilər - xüsusilə istifadəçi girişinə əsasən bu halda. FindAction metodu, açıqlama olmadan sadə bir NullPointerException'i partlatmaq üçün zəng üsulundan daha istisna seçsə daha yaxşı olardı.

 try { ParserFactory.getParser().findAction(someInput).doSomething(); } catch(ActionNotFoundException anfe) { userConsole.err(anfe.getMessage()); } 

Yoxsa cəhd / tutma mexanizminin çox çirkin olduğunu düşünürsünüzsə və heç bir şey etməsəniz, default tədbiriniz istifadəçi geribildirimini təmin etməlidir.

 public Action findAction(final String userInput) {  return new Action() { public void doSomething() { userConsole.err("Action not found: " + userInput); } } } 
2422
07 нояб. Cavab 07 noyabr tarixində verilmişdir. 2008-11-07 15:06 '08 at 15:06 2008-11-07 15:06

JetBrains IntelliJ IDEA , Eclipse və ya NetBeans kimi bir Java IDE istifadə etsəniz (və ya planlaşdırırsınızsa) və ya tapıntılar kimi bir vasitə varsa, bu problemi həll etmək üçün əlavə məlumatlar istifadə edə bilərsiniz.

Əsasən @Nullable@NotNull .

Metod və parametrlərdə istifadə edə bilərsiniz, məsələn:

 @NotNull public static String helloWorld() { return "Hello World"; } 

və ya

 @Nullable public static String helloWorld() { return "Hello World"; } 

İkinci misal tərtib edilməyəcək (IntelliJ IDEA-da).

Başqa bir kod helloWorld() ilk helloWorld() funksiyasını istifadə etdikdə:

 public static void main(String[] args) { String result = helloWorld(); if(result != null) { System.out.println(result); } } 

İndi IntelliJ IDEA kompilyatoru, check-in faydasız olduğunu bildirir, çünki helloWorld() funksiyası null qayıtsın.

Parametrləri istifadə edin

 void someMethod(@NotNull someParameter) { } 
border=0

Əgər belə bir şey yazarsanız:

 someMethod(null); 

Bu tərtib edilməyəcək.

@Nullable istifadə edərək son nümunə

 @Nullable iWantToDestroyEverything() { return null; } 

Bunu edirlər

 iWantToDestroyEverything().something(); 

Və əmin ola bilərsiniz ki, bu baş verməyəcək. :)

Bu, kompilyatorun adi haldan daha çox şeyi yoxlamaq və müqavilələrinizi gücləndirməsinin yaxşı bir yoludur. Təəssüf ki, bütün kompilyatorlar tərəfindən dəstəklənmir.

IntelliJ IDEA 10.5 və ondan sonra, hər hansı digər @Nullable @NotNull tətbiqlərinə dəstək əlavə etdi.

Blog girişinə baxın. Daha çox çevik və özelleştirilebilir @ Nullable / @ NotNull ek notlar .

528
05 марта '10 в 13:31 2010-03-05 13:31 Cavab Luca Molteni tərəfindən 05.03.2010 tarixində saat 13: 31-də 2010-03-05 13:31

Null dəyərlərə icazə verilmir

Metodunuz xaricə çağırılırsa, belə bir şeylə başlayın:

 public void method(Object object) { if (object == null) { throw new IllegalArgumentException("..."); } 

Sonra bu üsulun qalan hissəsində siz object null olmadığını görəcəksiniz.

Bu bir daxili metoddur (API-nın bir hissəsi deyil), sadəcə onu null və ola bilməz ki, sənədləşdirin.

Məsələn:

 public String getFirst3Chars(String text) { return text.subString(0, 3); } 

Lakin, əgər metodunuz sadəcə dəyəri keçərsə və növbəti üsul onu keçərsə və s. Bu problemli ola bilər. Bu halda, arqumenti yuxarıdakı kimi yoxlaya bilərsiniz.

Null icazə verilir

Bu, həqiqətən, asılıdır. Bunu tez-tez belə bir şey etdiyini görürsən:

 if (object == null) { // something } else { // something else } 

Beləliklə, mən cins və iki tamamilə fərqli şeylər edirəm. Çirkin kod parçası yoxdur, çünki məlumatlara görə iki fərqli şeyi etmək lazımdır. Məsələn, girişlə işləməliyəmmi və ya yaxşı bir dəyərini hesablamalıyam?


Mən, həqiqətən, if (object != null ... ) idiom istifadə etmək nadir hallarda var.

Ümumiyyətlə deyim istifadə etdiyiniz nümunələri göstərsəniz nümunələr vermək daha asan ola bilər.

286
07 нояб. cavab myplacedk 07 nov tərəfindən verilir . 2008-11-07 12:27 '08 at 12:27 pm 2008-11-07 12:27

Vay, NullObject pattern tövsiyə etmək üçün 57 fərqli NullObject pattern demək olar ki, başqa bir cavab əlavə etmək istəmirəm, amma düşünürəm ki, bu sual ilə maraqlanan bəzi insanlar Java 7-də əlavə etmək üçün " null təhlükəsiz emal " - if-not-bərabər-boşluğun mənbəyi üçün sadələşdirilmiş sintaksis.

Alex Miller tərəfindən verilmiş nümunə belədir:

 public String getPostcode(Person person) { return person?.getAddress()?.getPostcode(); } 

?. yalnız boş identifikatorun bağlantısını ləğv etmək deməkdir, əgər null deyilsə, əks halda ifadənin qalan hissəsini null olaraq qiymətləndirin. Postun üzvü Dick Wall və Devoxx seçiciləri kimi bəzi insanlar, həqiqətən, bu təklifi sevirlər, amma həqiqətən nəzarət dəyər kimi sıfırdan daha çox istifadə etməyi təşviq edəcəkləri səbəbiylə müxalifət var.


Yeniləmə: Java 7-də sıfır operator üçün rəsmi təklif layihə cinsinə göndərildi . Sintaksis yuxarıda göstərilən nümunədən bir qədər fərqlənir, lakin eyni konsepsiya.


Yeniləmə. Sıfır təhlükəsiz operatorla təklif layihə puluna daxil edilməyib. Beləliklə, Java 7-də bu sözdizimi görməyəcəksiniz.

216
17 янв. Cavab erickson tərəfindən verilir 2009-01-17 08:08 '09 saat 08:08 'da 2009-01-17 08:08

Tanımsız dəyərlərə icazə verilmirsə:

IDE-ni potensial sıfır dereference sizi xəbərdar etmək üçün qura bilərsiniz. Məsələn, Eclipse'de Parametrlər> Java> Kompilyator> Səhvlər / Uyarılar / Sıfır təhlili baxın.

Tanımsız dəyərlərə icazə verilirsə:

Əgər müəyyənləşdirilməmiş dəyərlərin məlum olduğu yeni bir API müəyyən etmək istəyirsinizsə , Option şablonundan istifadə edin (funksional dilləri ilə tanış ola bilərsiniz). Aşağıdakı üstünlüklərə malikdir:

  • API bir giriş və ya çıxış mövcud olub-olmadığını açıq şəkildə ifadə edir.
  • Derleyici, "qeyri-müəyyən" halda idare etmenizi zorlar.
  • Variant bir monaddır , buna görə də düzgün sıfırların yoxlanılmasına ehtiyac yoxdur, yalnız dəyəri (məsələn) etibarlı şəkildə istifadə etmək üçün xəritə / foreach / getOrElse və ya oxşar kombinatordan istifadə edin.

Java 8, Optional daxili sinifə malikdir (tövsiyə olunur); əvvəlki versiyalarda kitabxana alternativləri, məsələn, Optional Guava Option və ya FunctionalJava var . Lakin, bir çox funksional şablon kimi, Java-da (hətta 8) Seçim istifadə edərək, Scala və ya Xtend kimi daha az ətraflı JVM dilini istifadə edə biləcəyiniz bir sıra nümunələrə gətirib çıxarır.

NULL dəyərlərini geri ala biləcək bir API ilə məşğul olmanız lazım olsa, Java'da çox şey edə bilməzsiniz. Xtend və Groovy-də Elvis operatoru ?:null-safe dereference operator ?. lakin bu null istinad halda null qaytarır, belə ki, sadəcə boş dəyər düzgün idarə "ləğv" qeyd edin.

178
14 янв. Cavab yanvarın 14-də verilir 2010-01-14 16:45 '10 saat 16:45 'da 2010-01-14 16:45

Yalnız bu vəziyyət üçün -

Eşitlik üsulunu çağırmadan əvvəl dəyişənin null olmadığını yoxlayın (aşağıda simli müqayisə nümunəsi):

 if ( foo.equals("bar") ) { // ... } 

foo mövcud deyilsə, bir NullPointerException səbəb olacaq.

String aşağıdakı kimi müqayisə edərək bunu qarşısını almaq olar:

 if ( "bar".equals(foo) ) { // ... } 
163
09 нояб. Cavab verildi 09 noyabr. 2008-11-09 15:24 '08 at 15:24 2008-11-09 15:24

Java 8-də yeni bir sinf java.util.Optional , bəlkə də bəzi problemləri həll edir. Biri kodun okunabilirliğini yaxşılaşdırdığını və ictimai API'lar halında API arayüzünün işini geliştirici müştəri ilə asanlaşdırdığını söyləyə bilər.

Onlar bu kimi işləyirlər:

Bu tip ( Fruit ) üçün isteğe aid bir obyekt metodun qaytarılması növü olaraq yaradılır. Boş ola və ya Fruit obyekti ola bilər:

 public static Optional<Fruit> find(String name, List<Fruit> fruits) { for (Fruit fruit : fruits) { if (fruit.getName().equals(name)) { return Optional.of(fruit); } } return Optional.empty(); } 

Artıq bu meyvəyə baxın, bu Meyvə nümunəsi üçün Fruit siyahısına ( fruits ) baxın:

 Optional<Fruit> found = find("lemon", fruits); if (found.isPresent()) { Fruit fruit = found.get(); String name = fruit.getName(); } 

Bir hesabı yerinə yetirmək üçün map() operatorunu istifadə edə bilərsiniz - ya da isteğe bağlı bir obyektdən bir dəyər ala bilərsiniz. orElse() itkin dəyərlər üçün bir backup təmin etməyə imkan verir.

 String nameOrNull = find("lemon", fruits) .map(f -> f.getName()) .orElse("empty-name"); 

Əlbəttə, null / boş bir çek hələ də vacibdir, lakin ən azı geliştirici dəyərin boş olacağını və yoxlanılmayı unutma riskinin məhdud olduğunu bilir.

Optional istifadə edərək sıfırdan yaradılan bir API-da, qaytarma dəyəri boş olanda və sadə bir obyekti yalnız null olarsa (bir konvensiya) qaytarırsa, müştəri kodu qaytarılmış obyektlərin dəyərlərinə null çekləri rədd edə bilər ...

Əlbəttə, Optional , bəzi hallarda 5 və ya 10 artıq yükləmə metodundan daha çox seçmə argumentləri müəyyənləşdirmək üçün bir metod mübahisəsi kimi istifadə edilə bilər.

Optional olaraq, orElse dəyərini istifadə etməyə imkan verən və ifPresent lambda ifadələri ilə işləyən ifPresent kimi elə əlverişli üsullar təklif olunur.

NullPointerException (və ümumiyyətlə null pointer) problemi ilə yanaşı Optional tərəfindən gətirilən (qismən) həll də bu məqaləni oxumağa dəvət edirəm ( Əlavə Java obyektləri) .

137
25 апр. Apr 25-də Pierre Henri'ye cavab verdi 2013-04-25 18:22 '13 at 6:22 PM 2013-04-25 18:22

Nəzarət etdiyiniz obyektlərdən asılı olaraq, məsələn, apache commons > və apache kolleksiyası koleksiyonları

Məsələn:

 String foo; ... if( StringUtils.isBlank( foo ) ) { ///do something } 

və ya (yoxlamaq üçün nə lazımdırsa):

 String foo; ... if( StringUtils.isEmpty( foo ) ) { ///do something } 

StringUtils sinfi bir çoxundan biridir; Commonsda sıfır təhlükəsiz manipulyasiya edən bir neçə yaxşı sinif var.

Apache kitabxanasını (commons->

 public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) { Validate.notNull(validationEventHandler,"ValidationHandler not Injected"); return read(new StringReader(xml), true, validationEventHandler); } 

Bahar istifadə etsəniz, Bahar da paketində eyni funksiyaya sahibdir, kitabxanaya baxın (bahar -2.4.6.jar)

Bu statik sinfi f-nin yayından istifadə etmə nümunəsi (org.springframework.util.Assert)

 Assert.notNull(validationEventHandler,"ValidationHandler not Injected"); 
113
07 нояб. Cavab verildi javamonkey79 07 Nov. 2008-11-07 12:10 '08 at 12:10 2008-11-07 12:10
  • Əgər obyektin null olmamalıdır (və ya səhvdir) düşünmək, istifadə edin.
  • Metodunuz boş parametrləri qəbul etmirsə, bunu javadoc-da deyir və təsdiqləyin.

Nesneyi yoxlamaq lazımdır! = Null, yalnız obyekt boş olanda işi idarə etmək istəyirsinizsə ...

Null / notnull parametrlərinə kömək etmək üçün Java7-a yeni əlavə əlavə etmək təklifi var: http://tech.puredanger.com/java7/#jsr308

87
07 нояб. Cavab verildi 07 noyabr. 2008-11-07 11:55 '08 at 11:55 2008-11-07 11:55

Mən "uğursuz sürətli" kodunun bir pərəstişkarıyam. Özünüzə soruş: Parametr sıfır olduqda faydalı bir şey edirsiniz? Kodunuzun bu vəziyyətdə nə etməsi lazım olduğunu dəqiq bir cavablandırmıyorsanız ... Yəni heç bir zaman sıfır olmamalı və sonra bunu nəzərə almadan və bir NullPointerException atmasına icazə verin. Çağırıcı kodu IllegalArgumentException istisnası kimi eyni NPE dəyərinə malik olacaq, lakin geliştiricinin NPE-nin atılması halında yanlış nəyin baş verdiyini anlama və başa düşməsi üçün daha asan olacaq, bunun nəticəsi olan mantığın bəzi gözlənilməz gözlənilməz hadisələrini yerinə yetirməyə çalışır. ərizə hələ də işləmir.

81
23 мая '11 в 21:18 2011-05-23 21:18 cavab 23 May 'da 21:18' də Alex Worden tərəfindən verildi 2011-05-23 21:18

Bəzən simmetrik əməliyyat müəyyən edən parametrləri ilə işləyən üsullar var:

 af(b); <-> bf(a); 

Əgər b sıfır ola bilməyəcəyini bilirsinizsə, onu dəyişə bilərsiniz. Eşitlik üçün ən faydalıdır: foo.equals("bar"); əvəzinə foo.equals("bar"); "bar".equals(foo); etmək daha yaxşıdır "bar".equals(foo); .

69
07 нояб. Yoxannes Schaub cavab verildi - litb 07 Nov. 2008-11-07 12:04 '08 at 12:04 2008-11-07 12:04

Google koleksiyonları strukturu sıfır doğrulamaya nail olmaq üçün gözəl və zərif bir yol təqdim edir.

Kitabxana sinfi bir üsula malikdir:

 static <T> T checkNotNull(T e) { if (e == null) { throw new NullPointerException(); } return e; } 

Və ( import static ) istifadə olunur:

 ... void foo(int a, Person p) { if (checkNotNull(p).getAge() > a) { ... } else { ... } } ... 

Və ya nümunənizdə:

 checkNotNull(someobject).doCalc(); 
69
29 дек. cavab 29 dekabrda user2427 tərəfindən verilir . 2008-12-29 16:50 '09 at 16:50 2008-12-29 16:50

Istifadəsinə malik olan sıfır obyekt modelinin yerinə, sıfır obyektin səhv olduğu halları nəzərdən keçirə bilərsiniz.

İstisna atıldığında, yığın izinə baxın və səhv edin.

67
07 нояб. Jim Nelson 07 noyabrda cavab verdi. 2008-11-07 11:50 '08 at 11:50 2008-11-07 11:50

Java 7-də requireNonNull() metodunun requireNonNull() yeni java.util.Objects köməkçi sinfi requireNonNull() . Bütün bunlar NullPointerException bir atış edir, əgər onun arqumenti null, ancaq bir az kodu təmizləyir. Məsələn:

 Objects.requireNonNull(someObject); someObject.doCalc(); 

Metod, istifadəçinin hər üç kodunu saxlaya biləcəyi qurucuda tapşırıqdan əvvəl yoxlanılması üçün ən faydalıdır:

 Parent(Child child) { if (child == null) { throw new NullPointerException("child"); } this.child = child; } 

olur

 Parent(Child child) { this.child = Objects.requireNonNull(child, "child"); } 
65
10 авг. Stuart Marks tərəfindən verilmiş cavab 10 Avqust. 2012-08-10 10:08 '12 at 10:08 2012-08-10 10:08

Zero bir problem deyil. Bu komple modelləşdirmə alətlərinin ayrılmaz bir hissəsidir. Proqram dünyanın dünyanın mürəkkəbliyini simulyasiya etməkdir və sıfır yükünü daşıyır. Null " Java Məlumatı" və ya "Bilinməyən" və s. Buna görə, bu məqsədlər üçün null istifadə etmək məsləhətdir. Mən "Zero Object" modelini seçməmişəm; Hesab edirəm ki, o, " qəyyumluq məsələsini kim qoruyacaq "
Qızımın adının nə olduğunu soruşsanız, mən sizə heç bir qız yoldaşım olmadığımı söyləyəcəyəm. Java'da null qayıdacağam. Alternativ olaraq, orada həll edilə bilməyən (və ya istəməyən) bir problemi göstərmək üçün bir həssas istisnanı atmaq və məlumatı istifadəçiyə çatan bir səhvə yenidən cəhd etmək və ya hesablamaq üçün yığın üstündə bir yerə göndərmək olar.

  1. "Bilinməyən bir sual" üçün "naməlum cavab" verin. (İşgüzar nöqteyi-nəzərdən doğru olduğu təqdirdə təhlükəli deyil). Istifadə etməzdən öncə bir üsul içərisində null üçün argümanların yoxlanılması bir neçə zəng edənləri çağırmadan əvvəl onları yoxlamaqdan azad edir.

     public Photo getPhotoOfThePerson(Person person) { if (person == null) return null; // Grabbing some resources or intensive calculation // using person object anyhow. } 

    Əvvəlki foto şəkil kitabxanamda var olmayan bir qızın fotoşəkilini almaq üçün normal bir məntiqi axınına gətirib çıxarır.

     getPhotoOfThePerson(me.getGirlfriend()) 

    Və bu, yeni Java API-yə uyğun gəlir (gözləyirik).

     getPhotoByName(me.getGirlfriend()?.getName()) 

    Daha çox "normal iş axını" bir şəxs üçün verilənlər bazasında saxlanılan bir fotoşəkil tapmaq imkanı verməməsinə baxmayaraq, bəzi digər hallar üçün aşağıda göstərildiyi kimi, bir cüt istifadə etdim.

     public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException public static MyEnum parseMyEnumOrNull(String value); 

    <alt> + <shift> + <j> (Eclipse-də javadoc yaradın) yazaraq nifrət etməli və ümumi API üçün üç əlavə söz yazmalısınız. Bu sənədləri oxumayanlardan başqa hər kəs üçün kifayətdir.

      

    və ya

      
  2. Bu çox nəzəri bir vəziyyətdir və əksər hallarda java null təhlükəsiz API (başqa 10 ildən sonra buraxıldıqda) üstünlük verməlidir, lakin NullPointerException Exception alt sinifidir. Beləliklə, ağlabatan bir tətbiqi ( javadoc ) tutmaq istəyən şərtləri göstərən bir Throwable formasıdır! İlk imtiyaz üstünlüyünü və ayrı-ayrı səhvlərin kodunu "normal" NullPointerException ( Java yaradıcılarına görə) istifadə etmək üçün mənim kimi bir NullPointerException tutmaq üçün uyğun NullPointerException .

     public Photo getGirlfriendPhoto() { try { return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName()); } catch (NullPointerException e) { return null; } } 

    Могут возникнуть вопросы:

    В. Что если getPhotoDataSource() возвращает значение null?
    О. Это деловая логика. Если мне не удастся найти фотоальбом, я покажу вам никаких фотографий. Что делать, если appContext не инициализирован? Этот метод бизнес-логики справляется с этим. Если одна и та же логика должна быть более строгой, то бросание исключения является частью бизнес-логики, а явная проверка на нуль должна использоваться (случай 3). Новый Java Null-safe API лучше подходит для того, чтобы указать выборочно, что подразумевает, и что не означает, что его инициализация будет неудачной в случае ошибок программиста.

    Q. Резервный код может быть выполнен и ненужные ресурсы могут быть захвачены.
    A. Это может произойти, если getPhotoByName() попытается открыть соединение с базой данных, создать PreparedStatement и, наконец, использовать имя человека в качестве параметра SQL. Подход к неизвестному вопросу дает неизвестный ответ (случай 1). Перед захватом ресурсов метод должен проверять параметры и при необходимости возвращать "неизвестный" результат.

    Q. Этот подход имеет штраф за производительность из-за открытия закрытия попытки.
    A. Программное обеспечение должно быть легко понятным и модифицированным во-первых. Только после этого можно было подумать о производительности, и только в случае необходимости! и там, где это необходимо! ( источник ) и многие другие).

    Ps. Такой подход будет разумным использовать, поскольку отдельный код обработки ошибок из "обычного" принципа кода разумно использовать в некотором месте. Рассмотрим следующий пример:

     public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) { try { Result1 result1 = performSomeCalculation(predicate); Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty()); Result3 result3 = performThirdCalculation(result2.getSomeProperty()); Result4 result4 = performLastCalculation(result3.getSomeProperty()); return result4.getSomeProperty(); } catch (NullPointerException e) { return null; } } public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) { SomeValue result = null; if (predicate != null) { Result1 result1 = performSomeCalculation(predicate); if (result1 != null  result1.getSomeProperty() != null) { Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty()); if (result2 != null  result2.getSomeProperty() != null) { Result3 result3 = performThirdCalculation(result2.getSomeProperty()); if (result3 != null  result3.getSomeProperty() != null) { Result4 result4 = performLastCalculation(result3.getSomeProperty()); if (result4 != null) { result = result4.getSomeProperty(); } } } } } return result; } 

    PPS. Для тех, кто быстро сжимается (и не так быстро читает документацию), я хотел бы сказать, что в своей жизни я никогда не видел исключения с нулевым указателем (NPE). Но эта возможность была специально разработана разработчиками Java, потому что NPE является подклассом Exception . У нас есть прецедент в истории Java, когда ThreadDeath является Error не потому, что на самом деле это ошибка приложения, а исключительно потому, что он не предназначен для того, чтобы быть пойманным! Сколько NPE подходит для Error чем ThreadDeath ! Но это не так.

  3. Проверьте "Нет данных" только в том случае, если это подразумевает бизнес-логика.

     public void updatePersonPhoneNumber(Long personId, String phoneNumber) { if (personId == null) return; DataSource dataSource = appContext.getStuffDataSource(); Person person = dataSource.getPersonById(personId); if (person != null) { person.setPhoneNumber(phoneNumber); dataSource.updatePerson(person); } else { Person = new Person(personId); person.setPhoneNumber(phoneNumber); dataSource.insertPerson(person); } } 

    а также

     public void updatePersonPhoneNumber(Long personId, String phoneNumber) { if (personId == null) return; DataSource dataSource = appContext.getStuffDataSource(); Person person = dataSource.getPersonById(personId); if (person == null) throw new SomeReasonableUserException("What are you thinking about ???"); person.setPhoneNumber(phoneNumber); dataSource.updatePerson(person); } 

    Если appContext или dataSource не инициализируется необработанной рабочей средой, NullPointerException убьет текущий поток и будет обработан Thread.defaultUncaughtExceptionHandler (для определения и использования вашего любимого регистратора или другого механизма уведомления). Если не задано, ThreadGroup # uncaughtException будет печатать stacktrace для системного err. Необходимо отслеживать журнал ошибок приложений и открывать проблему Jira для каждого необработанного исключения, которое на самом деле является ошибкой приложения. Программист должен исправить ошибку где-то в файле инициализации.

63
ответ дан Mykhaylo Adamovych 21 нояб. '11 в 15:58 2011-11-21 15:58

В конечном счете, единственный способ полностью решить эту проблему - использовать другой язык программирования:

  • В Objective-C вы можете сделать эквивалент вызова метода на nil , и абсолютно ничего не произойдет. Это делает ненужные проверки, но может сделать ошибки намного сложнее для диагностики.
  • В Nice , языке Java, существует две версии всех типов: потенциально-нулевая версия и не- null версия. Вы можете использовать методы только для непустых типов. Потенциально-нулевые типы могут быть преобразованы в непустые типы через явную проверку для null. Это значительно облегчает понимание необходимости нулевых проверок и того, где они не являются.
46
ответ дан Michael Borgwardt 29 июля '09 в 23:52 2009-07-29 23:52

Обычная "проблема" в Java действительно.

Во-первых, мои мысли об этом:

Я считаю, что плохо "есть" что-то, когда NULL передан, где NULL не является допустимым значением. Если вы не выходите из метода с какой-то ошибкой, значит, в вашем методе ничего не получилось, что неверно. Тогда вы, вероятно, вернете null в этом случае, а в методе получения вы снова проверите значение null, и оно никогда не закончится, и вы получите "if!= Null" и т.д.

Итак, IMHO, null должен быть критической ошибкой, которая предотвращает дальнейшее выполнение (то есть, где null не является допустимым значением).

Как я решаю эту проблему:

Во-первых, я следую этому соглашению:

  • Все общедоступные методы /API всегда проверяют свои аргументы для null
  • Все частные методы не проверяют значение null, поскольку они управляются методами (просто дайте умереть с исключением nullpointer в случае, если он не обрабатывается выше)
  • Единственными другими методами, которые не проверяют значение null, являются утилиты. Они публичные, но если вы их почему-то называете, вы знаете, какие параметры вы передаете. Это похоже на попытку кипятить воду в чайнике, не давая воды...

И, наконец, в коде первая строка общедоступного метода выглядит следующим образом:

 ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate(); 

Обратите внимание, что addParam() возвращает self, так что вы можете добавить дополнительные параметры для проверки.

Метод validate() будет отмечен флажком ValidationException , если какой-либо из параметров имеет значение null (отмеченный или не отмеченный флажок - это проблема дизайна/вкуса, но мой ValidationException отмечен).

 void validate() throws ValidationException; 

Сообщение будет содержать следующий текст, если, например, "планы" имеют значение null:

" Недопустимое значение аргумента null встречается для параметра [планы] "

Как вы можете видеть, второе значение в методе addParam() (строка) необходимо для пользовательского сообщения, потому что вы не можете легко обнаружить имя переменной pass-in, даже с отражением (в любом случае это не относится к этому сообщению)..).

И да, мы знаем, что за пределами этой строки мы больше не будем сталкиваться с нулевым значением, поэтому просто безопасно вызываем методы для этих объектов.

Таким образом, код чист, прост в обслуживании и читаемости.

33
ответ дан Oleg 15 марта '11 в 15:42 2011-03-15 15:42

В дополнение к использованию assert вы можете использовать следующее:

 if (someobject == null) { // Handle null here then move on. } 

Это немного лучше, чем:

 if (someobject != null) { ..... ..... ..... } 
32
ответ дан fastcodejava 17 авг. '10 в 6:59 2010-08-17 06:59

Задавая вопрос о том, что вы можете быть заинтересованы в стратегиях обработки ошибок. Архитектор вашей команды должен решить, как работать с ошибками. Существует несколько способов сделать это:

  • позволяют Исключениям пульсировать через - поймать их в "основном цикле" или в какой-то другой управляющей процедуре.

    • проверьте условия ошибок и соответствующим образом обработайте их

Конечно, посмотрите также на Aspect Oriented Programming - у них есть четкие способы вставить if( o == null ) handleNull() в ваш байт-код.

32
ответ дан xtofl 07 нояб. '08 в 12:27 2008-11-07 12:27

Просто не используйте значение null. Не допускайте этого.

В моих классах большинство полей и локальных переменных имеют значения, отличные от нуля, и я добавляю в код все заявления о заключении (всегда утверждаю) в коде, чтобы убедиться, что это принудительно (поскольку оно более кратким и более выразительным чем позволить ему появиться как NPE, а затем разрешить номер строки и т.д.).

Как только я принял эту практику, я заметил, что проблемы, похоже, исправились. Вы случайно поймали вещи в процессе разработки и осознали, что у вас слабое место.. и что еще более важно.. он помогает инкапсулировать проблемы с различными модулями, разные модули могут "доверять" друг другу и не более засорять код с конструкциями if = null else !

Это защитное программирование и в конечном итоге приводит к значительному улучшению кода. Всегда дезинфицируйте данные, например. здесь, применяя жесткие стандарты, и проблемы уходят.

 class C { private final MyType mustBeSet; public C(MyType mything) { mustBeSet=Contract.notNull(mything); } private String name = "<unknown>"; public void setName(String s) { name = Contract.notNull(s); } } class Contract { public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; } } 

Контракты похожи на тесты на мини-модуле, которые всегда работают, даже в производстве, и когда что-то не удается, вы знаете, почему, а не случайный NPE, вам нужно как-то понять.

30
ответ дан ianpojman 18 окт. '12 в 6:42 2012-10-18 06:42

Гува, очень полезная базовая библиотека от Google, имеет хороший и полезный API, чтобы избежать нулей. Я считаю UsingAndAvoidingNullExplained очень полезным.

Как объясняется в wiki:

Optional<T> - это способ замены нулевой ссылки T на ненулевое значение. Необязательный может либо содержать ненулевую ссылку T (в этом случае мы говорим, что ссылка "присутствует" ), или она может содержать ничего (в этом случае мы говорим, что ссылка "отсутствует" ). Это никогда сказал, что "содержит null".

İstifadə edin:

 Optional<Integer> possible = Optional.of(5); possible.isPresent(); // returns true possible.get(); // returns 5 
28
ответ дан Murat Derya Özen 23 марта '12 в 23:16 2012-03-23 23:16

Это очень распространенная проблема для каждого разработчика Java. Таким образом, в Java 8 есть официальная поддержка для решения этих проблем без загроможденного кода.

Java 8 представила java.util.Optional<T> . Это контейнер, который может содержать или не содержать ненулевое значение. Java 8 предоставил более безопасный способ обработки объекта, значение которого может быть нулевым в некоторых случаях. Это вдохновлено идеями Haskell и Scala .

В двух словах класс Option включает методы для явного рассмотрения случаев, когда значение присутствует или отсутствует. Однако преимущество по сравнению с нулевыми ссылками заключается в том, что класс Optional <T> заставляет вас думать о случае, когда значение отсутствует. Как следствие, вы можете предотвратить непреднамеренные исключения нулевого указателя.

В приведенном выше примере у нас есть домашняя служба factory, которая возвращает дескриптор нескольких устройств, доступных в доме. Но эти услуги могут быть или не быть доступными/функциональными; это означает, что это может привести к исключению NullPointerException. Вместо того, чтобы добавлять условие null if перед использованием какой-либо службы, включите ее в Необязательный <Service> .

ОТКЛЮЧЕНИЕ К ОПЦИИ <T>

Рассмотрим способ получения ссылки службы из factory. Вместо того, чтобы возвращать служебную ссылку, оберните ее опцией. Это позволяет пользователю API знать, что возвращенная услуга может быть или не быть доступной/функциональной, использовать защищенно

 public Optional<Service> getRefrigertorControl() { Service s = new RefrigeratorService(); //... return Optional.ofNullable(s); } 

Как вы видите, Optional.ofNullable() обеспечивает простой способ получения ссылки. Есть еще один способ получить ссылку Необязательный, либо Optional.empty() , и Optional.of() . Один для возврата пустого объекта вместо того, чтобы перенастроить нуль, а другой - для обертывания объекта, не подлежащего обнулению, соответственно.

ТАК КАК ЭТО ТОГО, ЧТОБЫ ИЗБЕЖАТЬ СЛЕДУЮЩЕЙ ПРОВЕРКИ?

После того, как вы завернули ссылочный объект, необязательно предоставляет множество полезных методов для вызова методов на завернутой ссылке без NPE.

 Optional ref = homeServices.getRefrigertorControl(); ref.ifPresent(HomeServices::switchItOn); 

Необязательный .ifPresent вызывает данный потребитель с ссылкой, если он является ненулевым значением. В противном случае он ничего не делает.

 @FunctionalInterface public interface Consumer<T> 

Представляет операцию, которая принимает один входной аргумент и не возвращает результат. В отличие от большинства других функциональных интерфейсов, потребитель, как ожидается, будет работать через побочные эффекты. Это так чисто и легко понять. В приведенном выше примере кода HomeService.switchOn(Service) вызывается, если ссылка необязательного удержания не равна нулю.

Мы используем тернарный оператор очень часто для проверки нулевого условия и возврата альтернативного значения или значения по умолчанию. Опция предоставляет другой способ обработки одного и того же условия без проверки нулевого значения. Необязательный .orElse(defaultObj) возвращает defaultObj, если опция имеет нулевое значение. Позвольте использовать это в нашем примере кода:

 public static Optional<HomeServices> get() { service = Optional.of(service.orElse(new HomeServices())); return service; } 

Теперь HomeServices.get() делает то же самое, но лучше. Он проверяет, уже ли инициализирована услуга. Если это тогда, верните то же самое или создайте новую новую услугу. Необязательный <T> .orElse(T) помогает вернуть значение по умолчанию.

Наконец, вот наш NPE, а также нулевой код без кода:

 import java.util.Optional; public class HomeServices { private static final int NOW = 0; private static Optional<HomeServices> service; public static Optional<HomeServices> get() { service = Optional.of(service.orElse(new HomeServices())); return service; } public Optional<Service> getRefrigertorControl() { Service s = new RefrigeratorService(); //... return Optional.ofNullable(s); } public static void main(String[] args) {  Optional<HomeServices> homeServices = HomeServices.get(); if(homeServices != null) { Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl(); refrigertorControl.ifPresent(HomeServices::switchItOn); } } public static void switchItOn(Service s){ //... } } 

Полный пост NPE, а также Null check-free code... Действительно? .

20
ответ дан Yogesh Devatraj 27 апр. '15 в 7:16 2015-04-27 07:16

Мне нравятся статьи из Nat Pryce. Вот ссылки:

В статьях есть также ссылка на репозиторий Git для Java Maybe Type, который мне интересен, но я не думаю, что он один может уменьшить проверка кода раздувания. После нескольких исследований в Интернете, я думаю, что != Null раздутие кода может быть уменьшено главным образом путем тщательного проектирования.

20
ответ дан Mr Palo 21 авг. '11 в 21:33 2011-08-21 21:33

Я пробовал NullObjectPattern , но для меня это не всегда лучший способ. Иногда бывает, когда "нет действия" не подходит.

NullPointerException - исключение Runtime, которое означает, что разработчики не работают, и с достаточным опытом он сообщает вам, где именно ошибка.

Теперь ответ:

Попробуйте сделать все ваши атрибуты и их аксессоры доступными как можно более частными или вообще не подвергать их клиентам. Разумеется, вы можете иметь значения аргументов в конструкторе, но, уменьшая область действия, которую вы не позволяете классу клиента передавать недопустимое значение. Если вам нужно изменить значения, вы всегда можете создать новый object . Вы проверяете значения в конструкторе только один раз , а в остальных методах вы можете быть почти уверены, что значения не равны нулю.

Конечно, опыт - лучший способ понять и применить это предложение.

Byte!

18
ответ дан OscarRyz 14 нояб. '08 в 1:08 2008-11-14 01:08

Вероятно, лучшей альтернативой Java 8 или новее является использование класса Optional .

 Optional stringToUse = Optional.of("optional is there"); stringToUse.ifPresent(System.out::println); 

Это особенно удобно для длинных цепочек возможных нулевых значений. Məsələn:

 Optional<Integer> i = Optional.ofNullable(wsObject.getFoo()) .map(f -> f.getBar()) .map(b -> b.getBaz()) .map(b -> b.getInt()); 

Пример того, как выбрасывать исключение в null:

 Optional optionalCarNull = Optional.ofNullable(someNull); optionalCarNull.orElseThrow(IllegalStateException::new); 

Java 7 представила метод Objects.requireNonNull , который может быть полезен, когда что-то нужно проверить для непустоты. Məsələn:

 String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase(); 
15
ответ дан Raghu K Nair 23 марта '16 в 3:03 2016-03-23 03:03

Могу ли я ответить на него в более общем плане?

Мы обычно сталкиваемся с этой проблемой, когда методы получают параметры так, как мы не ожидали (плохой вызов метода - ошибка программиста). Например: вы ожидаете получить объект, вместо этого вы получите нуль. Вы ожидаете получить String с хотя бы одним символом, вместо этого вы получите пустую строку...

Таким образом, нет никакой разницы между:

 if(object == null){ //you called my method badly! 

}

və ya

 if(str.length() == 0){ //you called my method badly again! } 

Они оба хотят удостовериться, что мы получили действительные параметры, прежде чем будем выполнять какие-либо другие функции.

Как упоминалось в некоторых других ответах, чтобы избежать описанных выше проблем, вы можете следовать шаблону Дизайн по контракту . См. http://en.wikipedia.org/wiki/Design_by_contract .

Чтобы реализовать этот шаблон в java, вы можете использовать аннотации ядра java, такие как javax.annotation.NotNull или использовать более сложные библиотеки, такие как Hibernate Validator .

Только образец:

 getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType) 

Теперь вы можете безопасно развить основную функцию вашего метода без необходимости проверки входных параметров, они защищают ваши методы от неожиданных параметров.

Вы можете сделать еще один шаг и убедиться, что в приложении могут быть созданы только действительные pojos. (образец с сайта валидатора спящего режима)

 public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; // ... } 
14
ответ дан Alireza Fattahi 12 февр. '14 в 14:41 2014-02-12 14:41

Я очень пренебрегаю ответами, которые предполагают использование нулевых объектов в каждой ситуации. Этот шаблон может разорвать контракт и похоронить проблемы глубже и глубже, вместо того, чтобы их решать, не говоря уже о том, что использование неправомерно создаст еще одну кучу кода шаблона, который потребует дальнейшего обслуживания.

В действительности, если что-то, возвращаемое из метода, может быть нулевым, а вызывающий код должен принять решение, должен быть более ранний вызов, который обеспечивает состояние.

Также имейте в виду, что шаблон нулевого объекта будет голоден, если использовать его без осторожности. Для этого - экземпляр NullObject должен делиться между владельцами, а не быть экземпляром unigue для каждого из них.

Также я бы не рекомендовал использовать этот шаблон, где тип должен представлять собой примитивное представление типа, например, математические объекты, которые не являются скалярами: векторами, матрицами, комплексными числами и объектами POD (обычные старые данные), которые означают для хранения состояния в виде встроенных типов Java. В последнем случае вы в конечном итоге вызываете методы getter с произвольными результатами. Например, что должен вернуть метод NullPerson.getName()?

Стоит рассмотреть такие случаи, чтобы избежать абсурдных результатов.

14
ответ дан spectre 12 апр. '14 в 16:27 2014-04-12 16:27
  • Не инициализировать переменные до нуля.
  • Если (1) невозможно, инициализируйте все коллекции и массивы пустым коллекциям/массивам.

Выполняйте это в своем собственном коде, и вы можете избежать!= нулевые проверки.

В большинстве случаев нулевые проверки, похоже, защищают циклы над коллекциями или массивами, поэтому просто инициализируйте их пустыми, вам не понадобятся никакие проверки нуля.

 // Bad ArrayList<String> lemmings; String[] names; void checkLemmings() { if (lemmings != null) for(lemming: lemmings) { // do something } } // Good ArrayList<String> lemmings = new ArrayList<String>(); String[] names = {}; void checkLemmings() { for(lemming: lemmings) { // do something } } 

В этом есть крошечные накладные расходы, но это стоит того, чтобы сделать более чистый код и меньше NullPointerExceptions.

13
ответ дан Stuart Axon 14 июня '13 в 16:05 2013-06-14 16:05

Это самая распространенная ошибка для большинства разработчиков.

У нас есть несколько способов справиться с этим.

Подход 1:

 org.apache.commons.> 

notNull (объект объекта, сообщение String)

Подход 2:

 if(someObject!=null){ // simply checking against null } 

Подход 3:

 @isNull @Nullable // using annotation based validation 

Подход 4:

 // by writing static method and calling it across whereever we needed to check the validation static <T> T isNull(someObject e){ if(e == null){ throw new NullPointerException(); } return e; } 
13
ответ дан Sireesh Yarlagadda 11 апр. '14 в 23:14 2014-04-11 23:14

Java 8 представила новый класс Необязательный в пакете java.util.

Преимущества Java 8 Дополнительно:

1.) Нулевые проверки не требуются.
2.) Во время выполнения не должно быть больше NullPointerException.
3.) Мы можем разработать чистые и опрятные API.

Необязательный - контейнерный объект, который может содержать или не содержать ненулевое значение. Если значение присутствует, isPresent() вернет true и get() вернет значение.

Для получения дополнительной информации см. Здесь oracle docs: - https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

9
ответ дан NeeruSingh 09 окт. '17 в 13:35 2017-10-09 13:35
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос