Perché il modello di progettazione oggetto nullo è migliore del controllo dell'oggetto nullo. Se consideriamo l'impronta di memoria nel modello di progettazione di oggetti nulli, creiamo un nuovo oggetto fittizio dello stesso tipo. Che mostra se abbiamo oggetto di grandi dimensioni e un gran numero di oggetti nullable nella query di ricerca, questo modello creerà quel numero di oggetti nulli che occuperà più memoria di un semplice controllo che per null che il mio costo ritardo ignorabile nelle prestazioni.Modello di progettazione oggetto nullo Vs controllo oggetti nulli
risposta
L'intero problema con null
è che se si tenta di accedere a un valore null
l'applicazione genererà uno NullPointerException
e interromperà.
per ridurre il numero di classe NullXXX
in questo oggetto null modello di progettazione (la sua realtà solo la fabbrica del design dattern, non un modello di per sé) si potrebbe fare un static final NullCustomer
che viene sempre restituito.
In Java 8 è possibile utilizzare l'approccio Optional per indicare quando una funzione non restituisce sempre valori. Questo approccio non obbliga a creare classi null arbitrarie che inquinano la struttura generale (si consideri che potrebbe dover refactoring anche quelle classi null).
Eclipse e IntelliJ offrono anche compilare le annotazioni di tempo @Nullable
, @NonNull
che danno avvisi del compilatore quando si accede potenziali null
oggetti. Tuttavia, molti framework non sono annotati. IntelliJ pertanto prova a discover those potential null accesses con analisi statica. Oltre ad adottare questo approccio, IntelliJ ed Eclipse utilizzano le proprie annotazioni (org.eclipse.jdt.annotation.NonNull
, com.intellij.annotations.NotNull
) che non sono compatibili. Ma puoi store the annotations outside of the code che funziona in IntelliJ. Eclipse vuole implementarlo anche in futuro. Il problema è che ci sono many frameworks providing this feature che ti danno molte annotazioni diverse che fanno lo stesso. C'era JSR-305 che è dormiente. Fornirebbe un'annotazione in javax
. Non conosco il motivo per cui non l'abbiano spinto oltre.
Solo per modificare questo "Eclipse vuole implementarlo anche in futuro": il supporto per le annotazioni esterne è stato rilasciato tramite Eclipse Mars (4.5). –
Un altro chiarimento: "IntelliJ ed Eclipse usano le proprie annotazioni (org.eclipse.jdt.annotation.NonNull, com.intellij.annotations.NotNull) che quelle non sono compatibili". C'è solo una cosa all'interno di queste annotazioni che può essere incompatibile: il '@ Target'. Eclipse fornisce due versioni, org.eclipse.jdt.annotation_1.x per 1.7 e versioni precedenti ("dichiarazione annotazioni"), e org.eclipse.jdt.annotation_2.x per 1.8 e versioni successive ("annota il tipo", dove l'obiettivo è " TYPE_USE' per un controllo molto più forte). Oltre a ciò, Eclipse può essere configurato per utilizzare qualsiasi serie di annotazioni null correttamente definite. –
La differenza principale (e probabilmente il vantaggio) di questo modello è distinzione. Pensa alla seguente definizione di metodo:
public static int length(String str);
Questo metodo calcola la lunghezza di una determinata stringa. Ma l'argomento potrebbe essere null
? Cosa farà il metodo? Lanciare un'eccezione? Restituisci 0? Ritorno -1? Noi non sappiamo.
Una soluzione parziale può essere ottenuta scrivendo un buon documento java. La soluzione successiva e leggermente migliore è l'uso delle annotazioni annotazione JSR305 @Nullable
o @NotNullable
che tuttavia può essere ignorata dallo sviluppatore.
Se invece si utilizza modello oggetto Nullo (ad esempio opzionale di guava o Java 8) il codice è simile al seguente:
public static int length(Optional<String> str);
Così sviluppatore deve preoccuparsi avvolgendo la stringa in opzionali e quindi capisce che l'argomento può essere nullo Tentativo di ottenere il valore da Opzionale che contiene eccezioni cause nulle che non sempre si verificano quando si lavora con regolare null
.
Ovviamente è giusto che l'utilizzo di questo modello causi un consumo aggiuntivo di CPU e memoria che tuttavia non è significativo nella maggior parte dei casi.
Il modello oggetto nullo (https://en.wikipedia.org/wiki/Null_Object_pattern) non è lo stesso di Opzionale. –
Il principale vantaggio di utilizzare Null Object piuttosto che null
è che l'utilizzo di null
si deve ripetere verifica di se tale oggetto è davvero null
, in particolare in tutti i metodi che richiedono tale oggetto.
In Java 8, si dovrà fare:
Object o = Objects.requireNotNull(o); //Throws NullPointerException if o is indeed null.
Quindi, se si dispone di un metodo che passano costantemente lo stesso oggetto in vari metodo, ogni metodo dovrà controllare che l'oggetto ricevuto non è null prima di usarlo.
Quindi, un approccio migliore consiste nell'avere un oggetto Null o Optional
(Java 8 e versioni successive) in modo tale che non sia necessario eseguire il controllo null per tutto il tempo. Invece uno:
Object o = optional.get(); //Throws NullPointerException if internal value is indeed null.
//Keep using o.
No (davvero) necessità di controllo null. Il fatto che tu abbia un Optional
significa che potresti avere un valore o nessuno.
Null oggetti non hanno effetti collaterali, perché di solito non fa nulla (di solito tutti i metodi è un metodo vuoto) quindi non c'è bisogno di preoccuparsi di prestazioni (colli di bottiglia/ottimizzazione/etc).
È ancora necessario verificare se l'opzione è presente e una NullPointerException è ancora qualcosa che si desidera evitare. È solo che, poiché è un optional, è ora ovvio che potrebbe essere assente. –
@JB Nizet davvero. Stavo cercando di sottolineare la mancanza di fare il controllo "null" ogni volta. –
Con le annotazioni null specificheresti tutti quei metodi come prendere un argomento @NonNull. Quindi il chiamante eseguirà un controllo/asser null sulla variabile locale in questione e passerà questa variabile in tutte le chiamate di metodo e tutto andrà bene. Inoltre: questo evita la potenziale confusione sulle chiamate ai metodi che dovrebbero svolgere un lavoro in quanto potrebbero essere vietate. –
Supponiamo di avere qualcosa di simile:
private SomeClass someField;
void someMethod() {
// some other code
someField.method1();
// some other code
someField.method2();
// some other code
someField.method3();
}
Ora supponiamo che ci siano casi d'uso valide quando someField
può essere null
e non si vuole invocare i suoi metodi, ma si desidera eseguire l'altra some other code
sezioni del metodo. Si avrebbe bisogno di implementare il metodo come:
void someMethod() {
// do something
if (someField != null) {
someField.method1();
}
// do something
if (someField != null) {
someField.method2();
}
// do something
if (someField != null) {
someField.method3();
}
}
Utilizzando oggetto Null con i metodi vuoti (no-op) evitiamo boilerplate controlli nulli (e la possibilità di dimenticare di aggiungere i controlli per tutte le occorrenze).
Spesso lo trovo utile in situazioni in cui qualcosa viene inizializzato in modo asincrono o facoltativo.
In Java8, è possibile utilizzare Opzionale per evitare NullPointerExceptions senza eseguire ulteriori controlli. http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html – Stultuske
che dire di altri linguaggi come C# e C++ –
@MuhammadNasir più ne avrai esperienza, più ti renderai conto che un programma super veloce che non funziona o è pieno di bug è peggio di un programma abbastanza veloce che funziona bene. Tutto non riguarda le prestazioni e l'impronta della memoria. Evitare bug è più importante. 'null' è la fonte di molti bug e il controllo di null viene spesso dimenticato. –