2010-04-19 9 views
18

so che posso scoprire se una variabile è nullo in Java utilizzando queste tecniche:Scopri cosa variabile sta gettando un NullPointerException programmazione

  • se (var==null) -> troppo lavoro
  • try { ... } catch (NullPointerException e) { ...} -> racconta mi quale linea sta gettando l'eccezione
  • utilizzando il debugger -> a mano, troppo lento

Considerate questa riga di codice:

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

Vorrei sapere se esiste un modo generico per scoprire in modo programmatico quale variabile (non solo la riga) sta lanciando NullPointerException in una determinata area di codice. Nell'esempio, sapendo che

+5

Hm, sarebbe più facile trovare il NullPointerException se questo non era 't un one-liner. È davvero difficile seguire questo codice. –

+10

Considerando le tue opzioni, vorrei solo sottolineare che "troppo lavoro" potrebbe effettivamente significare molto meno lavoro a lungo termine. –

+3

Trasformalo in un blocco corretto. Troverai il problema in pochissimo tempo. – Geo

risposta

25

Poiché è possibile causare un'eccezione puntatore nullo senza nemmeno coinvolgere una variabile:

throw new NullPointerException(); 

avrei dire che non v'è alcun modo generico da definire un'eccezione di puntatore nullo a una variabile specifica.

La soluzione migliore sarebbe inserire il minimo di istruzioni possibili su ciascuna riga in modo che diventi ovvio che cosa ha causato l'eccezione del puntatore nullo. Considerate refactoring il codice in questione per cercare qualcosa di simile:

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

E 'più righe di codice per essere sicuri. Ma è anche più leggibile e più manutenibile.

+0

ci sono linguaggi che possono dirti quale variabile è responsabile? (o IDE)? – ycomp

1

so che lei ha suggerito che (var==null) è troppo lavoro, ma, come Miguel ha dichiarato nei commenti, è quello che vorrei andare con.

2

Cosa intendi con "uso del debugger -> a mano, troppo lento"? Se il tuo codice è strutturato correttamente, non ci saranno più di due o tre variabili usate sulla stessa linea. È così lento controllarli? Non hai NullPointers ogni minuto.

+1

> Cosa intendi con "usare il debugger -> a mano, troppo lento"? - Ad esempio, dalla mia esperienza, quando è necessario eseguire il debug in remoto. Ma a volte l'allegato del debugger remoto non è nemmeno possibile. – gumkins

6

Siamo spiacenti, no, non esiste un modo programmatico semplice per determinare quale variabile o chiamata di metodo è la fonte dell'eccezione. Potresti usare qualcosa come Aspect-Oriented Programming (AOP), ad es. AspectJ, ma questo non è inerente alla lingua e non è generalmente incorporato in un programma semplicemente per scopi di debug.

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

So che non vuoi sentire questo, ma queste sono semplicemente il costo di fare business.

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

È insolito vedere così tante chiamate di metodo messe insieme. Credo che la cosa migliore da fare sia prendere l'abitudine di suddividerle di più - non necessario fino a 1 chiamata per linea, ma meno di questa. Perché?

1) Correctness - è valido nella progettazione di una di queste chiamate per restituire null?Se è così, dovresti romperlo, testarlo e gestirlo in modo appropriato.

2) Understandability - sarebbe più facile per i manutentori future (compresi futuro si) per capire se si intermedie, variabili ben chiamati a contribuire a chiarire ciò che sta accadendo su questa linea.

3) Efficiency - di solito quando si va così in profondità in un grafico (mettendo insieme una serie di chiamate di metodo), è probabile che sia necessario tornare indietro più tardi. Catturare questo valore intermedio in una variabile intermedia significa evitare di ripetere una o più chiamate di metodo.

4) Debugging - come indicato dalla tua domanda, splittando una linea complessa come questa semplifica il debug. restringendo la possibile fonte dell'eccezione.

1

Penso che dovresti notare Demeters Law.

Non ci sono molte persone che lo seguono rigorosamente, perché risulta in molti metodi delegati.
Ma allontanarsi troppo da esso porterà a dipendenze da strutture interne che dovrebbero essere trasparenti.

+2

Solo perché le cose sono legate insieme, non significa che violate la legge di Demetra. È principalmente quando stai afferrando un riferimento attraverso il concatenamento, quindi modificando qualcosa. Non c'è niente di sbagliato nel raggiungere il basso per visualizzare o confrontare un valore in modalità di sola lettura. –

0

Ciò che ha funzionato in modo eccellente per me è l'eccezione in cui normalmente viene generato e quindi utilizza Log per vedere se qualcuno di essi ha valori "nulli".

Il mio codice:

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); 
      } 
Problemi correlati