2010-04-19 10 views
18

wiem, że mogę dowiedzieć się, czy zmienna ma wartość null w Javie za pomocą tych technik:Sprawdzaj co zmienna rzuca NullPointerException programowo

  • jeśli (var==null) -> zbyt dużo pracy
  • try { ... } catch (NullPointerException e) { ...} -> mówi mi co linia rzuca wyjątek
  • pomocą debuggera -> ręcznie, zbyt powolne

Rozważmy następujący wiersz kodu:

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0) { 

Chciałbym wiedzieć, czy istnieje ogólny sposób, aby dowiedzieć się programowo, która zmienna (nie tylko linia) rzuca wyjątek NullPointerException w określonym obszarze kodu. W tym przykładzie, wiedząc, że

+5

Hm, byłoby łatwiej znaleźć NullPointerException jeśli to nie był „t one-liner. Naprawdę trudno jest śledzić taki kod. –

+10

Biorąc pod uwagę twoje opcje, chciałbym tylko wskazać, że "zbyt dużo pracy" może w rzeczywistości oznaczać o wiele mniej pracy na dłuższą metę. –

+3

Zmień to w odpowiedni blok. Problem pojawi się w mgnieniu oka. – Geo

Odpowiedz

25

Ponieważ jest to możliwe, aby spowodować wyjątku null pointer, nawet z udziałem zmienną:

throw new NullPointerException(); 

musiałbym powiedzieć, że nie ma rodzajowe sposób zmusić wyjątku null pointer do określonej zmiennej.

Najlepszym rozwiązaniem byłoby umieszczenie jak najmniejszej liczby instrukcji w każdym wierszu, aby stało się oczywiste, co spowodowało wyjątek wskaźnika pustego. Rozważmy refaktoryzacji kodu w pytaniu wyglądać mniej więcej tak:

List items = this.superSL.items; 
String name = items.get(name); 
String source = name.getSource(); 
if (source.compareTo(VIsualShoppingList.Source_EXTRA) == 0) { 
    // ... 
} 

To więcej linii kodu, aby mieć pewność. Ale jest również bardziej czytelny i łatwiejszy w utrzymaniu.

+0

Czy istnieją języki, które mogą ci powiedzieć, która zmienna jest odpowiedzialna? (lub IDE)? – ycomp

1

Wiem, że sugerujesz, że (var==null) jest zbyt dużo pracy, ale, jak Miguel stwierdził w komentarzach, to jest to, co chciałbym zrobić.

2

Co rozumiesz przez "używanie debuggera -> ręcznie, zbyt wolno"? Jeśli twój kod jest właściwie skonstruowany, nie będzie więcej niż dwie lub trzy zmienne używane w tej samej linii. Czy tak wolno je sprawdzać? Nie masz NullPointers co minutę.

+1

> Co rozumiesz przez "używanie debuggera -> ręcznie, zbyt wolno"? - Na przykład z mojego doświadczenia, kiedy trzeba zdalnie debugować. Ale czasami zdalny dodatek do debuggera nie jest nawet możliwy. – gumkins

6

Niestety, nie ma prostego programowego sposobu określania, która zmienna lub wywołanie metody jest źródłem wyjątku. Możesz użyć czegoś takiego, jak Aspect-Oriented Programming (AOP), np. AspectJ, ale nie jest to związane z językiem i zazwyczaj nie jest włączone do programu w celu debugowania.

  • if (var==null) -> too much work
  • try { } catch() { }
  • Debugger

Wiem, że nie chcesz tego słuchać, ale są to po prostu koszt prowadzenia działalności gospodarczej.

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0) { 

Nieczęsto spotyka się tak wiele nawiązywanych połączeń metod. Uważam, że najlepiej jest nabrać nawyku łamania tego bardziej - niekoniecznie do 1 połączenia na linię, ale mniej niż to. Czemu?

1) Correctness - czy jest ważny w projekcie jednego z tych połączeń, aby zwrócić wartość null?Jeśli tak, powinieneś go wyłuskać, przetestować i odpowiednio obsłużyć.

2) Understandability - byłoby łatwiej dla przyszłych opiekunów (w tym przyszłości ty), aby zrozumieć, jeśli pośrednie, dobrze nazwane zmienne, które pomogą wyjaśnić, co dzieje się na tej linii.

3) Efficiency - zazwyczaj gdy zagłębimy się w wykres (łącząc serię wywołań metod), najprawdopodobniej trzeba będzie tam wrócić później. Przechwytywanie tej wartości pośredniej w zmiennej pośredniej oznacza unikanie ponownego wykonywania jednego lub więcej wywołań metod.

4) Debugging - jak wskazano w pytaniu, spltowanie tak złożonej linii upraszcza debugowanie. przez zawężenie możliwego źródła wyjątku.

1

Myślę, że powinieneś zauważyć Demeters Law.

Nie ma zbyt wielu osób przestrzegających go ściśle, ponieważ powoduje to wiele metod delegowania.
Ale odejście od niego spowoduje uzależnienia od wewnętrznych struktur, które powinny być przezroczyste.

+2

To, że rzeczy są ze sobą powiązane, nie oznacza, że ​​naruszasz prawo Demeter. Dzieje się tak głównie wtedy, gdy przechwytujesz referencję przez łańcuch, a następnie modyfikujesz coś. Nie ma nic złego w osiągnięciu, aby wyświetlić lub porównać wartość w trybie tylko do odczytu. –

0

To, co zadziałało naprawdę pięknie, to łapanie wyjątku tam, gdzie zwykle jest rzucane, a następnie używanie Logu, aby sprawdzić, czy któryś z nich ma wartości "null".

Mój kod:

try { 
       if (description_visible) advice_title_cur.setText(all_title_array[pos]); 
       else advice_title_cur.setText(all_title_array[pos] + "..."); 

      } catch (NullPointerException e) { 
       e.printStackTrace(); 
       Log.e("My name", "description_visible " + description_visible); 
       Log.e("My name", "advice_title_cur " + advice_title_cur); 
       Log.e("My name", "all_title_array " + all_title_array); 
       Log.e("My name", "pos " + pos); 
      } 
Powiązane problemy