2012-02-06 21 views
11

Ovviamente uno dei più grandi divieti di programmazione Java è l'eccezione null e puntatore nullo. Quali sono gli schemi di progettazione che non aggiungono troppo al codice ma riducono il problema delle eccezioni di null-pointer della sabbia?Quali sono i buoni schemi di progettazione leggeri per evitare i nulli in Java?

+0

Abbiamo davvero bisogno di un modello per il controllo di nullpointer? Usare qualcosa come commonsutil non dovrebbe essere sufficiente? – kosa

+1

"Ovviamente uno dei più grandi divieti"? NullPointerExceptions è uno dei tipi di problemi più facili da diagnosticare. –

+0

@thinksteep, se lo fai molto e si può stabilire un buon modello, allora è utile. Questo è particolarmente vero se il modo in cui viene gestito normalmente è dettagliato. – Joe

risposta

11

Null Object pattern. Guarda la classe Optional da google-guava library.

Il wiki ha un article sull'utilizzo e sull'eliminazione dei valori nulli.

+0

Sapevo che google-guava aveva un sacco di chicche eccellenti. Non sapevo che affrontasse questo problema. – Joe

+0

in che modo il pattern Null Object può ridurre il problema delle eccezioni di null-pointer della sabbia? – UmNyobe

+0

@UmNyobe: se si dispone di un oggetto anziché null, non è possibile ottenere NullPointerException. –

4

Il miglior modello di progettazione di tutti - il check-Not Null Idiom

if(obj != null) { 
    ... 
} 
+2

Definitivamente non è il modello migliore. Controlla questo: 'object.get(). DoSomething(). DoMore(). StillProcessing(). Yep(). GotIt()' (: – Marcelo

+0

È un modello discreto ma non molto di un design-bit vero?: –

+2

Vedo un sacco di codice che usa questo idioma e generalmente mi fa rabbrividire - a meno che non ci sia un "altro" associato a quel "se", tendo a pensare che ci stiamo spostando verso il territorio del "comportamento indefinito". – DaveH

3

Basta abituarsi a non tornare oggetti nulli sui vostri metodi.

public MyObject bohemianRhapsody(){ 

    try { 
     if(isThisTheRealLife()) 
      return new MyObject("is this just fantasy"); 
     else 
      return new MyObject("caught in a landslide, no escape from reality"); 
    } catch(ExampleCatchableException e){ 
     return new MyObject(""); // instead of return null 
    } 
} 

... 
System.out.println(bohemianRhapsody()); // will never print null 

Anche (tipo di) denominato Null-Object pattern.

+0

Nel mio codice lancio felicemente qualsiasi eccezione che si verifica. – UmNyobe

+0

Questo non è il modello Null-Object. C'è una differenza tra una stringa vuota e null. Il codice di richiamo (che hai reso pubblico dopotutto) potrebbe ragionevolmente prendere decisioni in base al fatto se ciò che è stato restituito fosse nullo o vuoto. –

+0

@GeorgeMauer, potrebbe utilizzare molto ragionevolmente il risultato direttamente sull'interfaccia - nel qual caso, è meglio mostrare "null" o nulla? – Marcelo

3

Perché si desidera evitare l'eccezione del puntatore nullo? Ottenere null quando ci si aspetta qualcos'altro è una delle prime indicazioni che qualcosa non va quando si scrive codice. Cose come Null Object Pattern dovrebbero essere utilizzate quando si è sicuri che sia adeguata. Uno dei maggiori svantaggi del design pattern è il loro abuso/abuso.

EDIT:

Penso che il modo migliore per ridurre il ritorno nulla sarà quello di aumentare l'uso di eccezioni. Pensate a un elenco che restituisce un oggetto null quando si tenta di accedere all'elemento in corrispondenza dell'indice -1, si prevede di utilizzare le cose come

if(list.get(-1).equals(nullObject))

che è ancora peggio. Credo che sia meglio sollevare un'eccezione quando gli argomenti sono inattesi o incompatibili.

+0

Altre eccezioni controllate sono preferibili ai puntatori nulli. Non mi piacciono i puntatori nulli perché indicano che qualcosa non va, ma lo fanno in RUN-TIME. Qualcosa come Null Object Pattern è migliore, perché il tuo codice traccia l'errore e può fornire un antidoto logico al problema. – Joe

2

Immagino che sia una questione di gusti, ma direi che i più grandi divieti di linguaggi come Smalltalk/Objective-C è che NON hanno nulla e che NON ci sono NullPointerExceptions. Non sono un fan di "Null object pattern", infatti lo detesto con passione perché trovo che sia in grado di risolvere i problemi e trovare bug in modo molto più difficile senza alcun beneficio reale. Null ha un significato (spesso cattivo) e non deve essere trattato come qualsiasi altro stato generico.

Come è stato menzionato in questa discussione, NPE è davvero potente e un buon modo per rilevare errori sintattici o codifica errata all'inizio e if (obj != null) è piuttosto semplice. Se l'applicazione inizia a generare NPE in fase di esecuzione, hai fatto qualcosa di sbagliato e devi risolverlo. Non cercare di nascondere l'eccezione, correggi ciò che è CAUSANDO l'eccezione.

+0

L'eccezione di puntatore nullo è un'eccezione non controllata. Quindi il problema è che non conoscerai il problema fino al runtime. È molto meglio che il tuo codice sia scritto per rispondere senza avere alcun valore per qualcosa in primo luogo. – Joe

+0

Naturalmente. Ecco perché controlli la nullità. Quello che trovo comunque spaventoso, è quando un valore può essere nullo senza causare una reazione chiara e corretta (come un NPE). L'idea di "null è anche un oggetto" in Smalltalk/Obj-c lo trovo semplicemente terrificante. Null non è un valore, è null. – pap

+1

Ma che dire di un oggetto nullo che incapsula l'esistenza di un errore e persino di controllare le eccezioni quando viene usato dopo che è stato impostato. Il problema con il controllo della nullità è che siamo umani e possiamo dimenticare di farlo. Null interrompe fondamentalmente il modello di oggetti Java. Se non ritieni di aver bisogno di un linguaggio che ti tenga la mano e ti ricordi di fare le cose, saresti più produttivo in un linguaggio che ha una digitazione più debole rispetto a Java. – Joe

2
"something definetly not null".equals(maybeNullVar) 

vs

maybeNullVar.equals("something definetly not null") 
1

Questi metodi (vedi anche Commons Apache -lang) può ridurre l'onere dei controlli nulli nei casi di elaborazione String incapsulandoli in metodi che t preservare il significato semantico del codice:

public static boolean isBlank(final String str) 
{ 
    return (str == null) || str.isEmpty(); 
} 

public static boolean isNotBlank(final String str) 
{ 
    return !StringUtils.isBlank(str); 
} 

public static boolean isEqual(final String s1, final String s2) 
{ 
    if (s1 == s2) { return true; } 
    if ((s1 == null) || (s2 == null)) { return false; } 
    return s1.equals(s2); 
} 

public static boolean isNotEqual(final String s1, final String s2) 
{ 
    return !StringUtils.isEqual(s1, s2); 
} 
1

Non è necessario utilizzare alcun modello di progettazione.

Basta inizializzare le variabili durante la dichiarazione.

ad es.

List<String> names = new ArrayList<String>(); 
Map<String,String> pairs = new HashMap<String,String>(); 
Problemi correlati