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?
risposta
Null Object pattern. Guarda la classe Optional da google-guava library.
Il wiki ha un article sull'utilizzo e sull'eliminazione dei valori nulli.
Sapevo che google-guava aveva un sacco di chicche eccellenti. Non sapevo che affrontasse questo problema. – Joe
in che modo il pattern Null Object può ridurre il problema delle eccezioni di null-pointer della sabbia? – UmNyobe
@UmNyobe: se si dispone di un oggetto anziché null, non è possibile ottenere NullPointerException. –
Il miglior modello di progettazione di tutti - il check-Not Null Idiom
if(obj != null) {
...
}
Definitivamente non è il modello migliore. Controlla questo: 'object.get(). DoSomething(). DoMore(). StillProcessing(). Yep(). GotIt()' (: – Marcelo
È un modello discreto ma non molto di un design-bit vero?: –
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
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.
Nel mio codice lancio felicemente qualsiasi eccezione che si verifica. – UmNyobe
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. –
@GeorgeMauer, potrebbe utilizzare molto ragionevolmente il risultato direttamente sull'interfaccia - nel qual caso, è meglio mostrare "null" o nulla? – Marcelo
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.
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
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.
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
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
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
Ci sono alcune annotazioni servizievoli progettati per scopi thiese da IntellyJ: @Nullable e @NotNull
Detecting probable NPE’s
"something definetly not null".equals(maybeNullVar)
vs
maybeNullVar.equals("something definetly not null")
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);
}
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>();
Abbiamo davvero bisogno di un modello per il controllo di nullpointer? Usare qualcosa come commonsutil non dovrebbe essere sufficiente? – kosa
"Ovviamente uno dei più grandi divieti"? NullPointerExceptions è uno dei tipi di problemi più facili da diagnosticare. –
@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