2013-08-08 11 views
6

Perché Java lancia spesso un'eccezione di puntatore nullo se provo ad accedere a valori nulli mentre l'Objective C non lo fa?Java vs Objective C in caso di eccezione nullpointer

Java:

public class SubscribeEmailActivity { 
    String status; 

    public static void main(String[] args){ 

     if(Status.equals(null)||status.equals(""){ 

      // i am getting error here 

     } 
    } 

} 

Objective C:

//in .h file 
NSString *exp; 

//in .m file 
if ([exp isEqualToString:NULL] ||[exp isEqualToString:@""]) 
{ 
    // i am not getting any error 
} 
+9

Perché sono lingue diverse? Non esiste una regola assoluta su come una lingua deve gestire i metodi di chiamata su 'null'. È una decisione che gli sviluppatori della lingua hanno fatto per diversi motivi. – DrummerB

+0

ho lo stesso dubbio – ArunMak

+4

Non so Objective-c, ma [exp isEqualToString: NULL] non mi sembra un assegno per null, ma piuttosto un controllo per "NULL" e il controllo Java di null non ha senso . –

risposta

6

In ultima analisi, l'unico modo per risolvere completamente il problema è quello di utilizzare un linguaggio di programmazione diversa:

  • In Objective-C, si può fare l'equivalente di invocare un metodo su nulla, e nulla accadrà . Ciò rende superflua la maggior parte dei controlli nulli, ma può rendere gli errori molto più difficili da diagnosticare.
  • In Nice, un linguaggio derivato da Java, esistono due versioni di tutti i tipi: una versione potenzialmente nulla e una versione non nulla. Puoi solo invocare metodi su tipi non nulli. I tipi potenzialmente null possono essere convertiti in tipi non nulli tramite il controllo esplicito di null. Ciò rende molto più facile sapere dove sono necessari i controlli nulli e dove non lo sono.
7

Il problema è nella vostra valutazione in Java, dovrebbe essere:

if(status == null||status.equals("")) { 
    //Do not try to dereference status.... 

Va rilevato che questo solo funziona perché Java e altri linguaggi consentono scorciatoie nelle valutazioni logiche. Alcuni semplici algebra booleana in questo caso:

true || ??? => true 

Una volta che il primo termine restituisce true, sappiamo che l'OR condizionale sarà anche valutata come vera, non v'è alcuna necessità di esaminare il secondo termine.

È inoltre possibile utilizzare Apache Commons isEmpty() o rotolare il proprio:

public static final boolean isEmpty(String arg0) { 
    if(arg0 == null) return true; 
    if(arg0.trim().length() < 1) return true; 
    return false; 
} 

La versione mostrata è simile a isBlank in Apache Commons.

+0

status.equals ("") può anche essere scritto come status.isEmpty() – Carnal

+0

In realtà è possibile evitare entrambe le chiamate chiamando '" ".equals (status)'. In questo modo il metodo '.equals()' verrà * mai * chiamato su un oggetto nullo, e allo stesso tempo si sta verificando se la stringa è vuota quando 'status' non è nullo. – tomacco

2

Se la variabile status è null in Java, poi cercando di chiamare status.equals() sarà un'eccezione NullPointer. isEqualToString non è una funzione membro delle stringhe Objective-C, ma confronta semplicemente una stringa e un oggetto.

+1

isEqualToString: (i due punti sono importanti) è un metodo di classe NSString. – Fred

4

Questo probabilmente non rispondere alla tua domanda, ma una regola per evitare un'eccezione di puntatore nullo, e nello stesso tempo evitare un controllo di nulla, è quello di invertire il controllo in questo modo:

Status status = null; 
if("".equals(status)){ 
    //.... 
} 

che restituirà false.

durante l'utilizzo:

if(status.equals("")){ 
} 

sarà un'eccezione NPE.

+0

+1 per spiegare davvero la differenza – Carnal

2

È solo una questione di come è stato progettato il linguaggio. Puoi dare un'occhiata a here se sei abbastanza coraggioso, per vedere come funziona objc_msgSend e perché puoi inviare messaggi a oggetti nulli.

4

Nel metodo Objective C le chiamate sono considerate equivalenti all'invio di un messaggio e l'invio di un messaggio a nil non fa nulla. Ciò significa che non è necessario scrivere i controlli null che sarebbero necessari in Java, il che è più conveniente per i programmatori che possono scrivere codice più compatto.

D'altra parte, può anche essere una fonte di errore: se ci si aspettava di inviare un messaggio a un oggetto reale ma inviarlo a nil invece, nell'Obiettivo C non si otterrà un avviso. In Java questa operazione causa il lancio di NullPointerException, rendendo evidente che si è verificato un bug.

Poiché i progettisti di linguaggi devono fare un compromesso tra convenienza e sicurezza, nessuna delle due opzioni è oggettivamente migliore. I progettisti dell'Obiettivo C hanno deciso che è meglio implementare nil come un buco nero: ingoia tutto ciò che si butta su di esso. I progettisti di Java hanno deciso che è meglio se si trattasse di null generato un errore esplicito. Niente di più in realtà.

2

Nel codice

if(Status.equals(null)||status.equals("") si sta confrontando una stringa in null (null non è una stringa).

Non è possibile confrontare la stringa con una non stringa. In caso di codifica IOS Credo che

[exp isEqualToString:NULL]

converte argomento per nulla nullo o nullo sono stessi e poi confrontarla, quindi funziona.

Problemi correlati