2015-06-12 13 views
5

Il mio progetto ha codice come il seguente:concatenamento Null-Safe Operatore

params.stringValue?.trim().replaceAll('aa', 'a') 

Ci aspettavamo che se params.stringValue era nulla, che sia trim() e replaceAll() non sarebbe chiamato.

Tuttavia stavamo ottenendo un NullPointerException su questa riga dicendo che replaceAll() non può essere chiamato su un oggetto nullo.

Abbiamo dovuto cambiare il codice per essere come questo:

params.stringValue?.trim()?.replaceAll('aa', 'a') 

Perché il primo frammento di codice di cui sopra non funziona? È un bug in Groovy che continua a valutare l'espressione dopo che è stato rilevato un null una volta?

+0

Penso che sia una "funzionalità", piuttosto che un bug (!) – Armand

risposta

4

E 'il modo in cui funziona Groovy, infatti, e ha morso others:???.

println libro .author .firstName .trim() concat ("è grande".)

...

Guardando questa riga di codice, ho pensato di essere al sicuro da ogni subdolo NullPointerException. Se book, author o firstName sono nulli, finirò semplicemente per stampare null e non dovrò preoccuparmi del metodo concat(). Dopo tutto, se il metodo trim() ha successo, non ha senso custodire il risultato per null. Ed è qui che ho sbagliato.

ci sono stati almeno this discussion per cambiare la situazione:?

un .b.c // Non si vede l'errore? ;)

Otterrò un NullPointerException. Voglio dire, se usi il null-safe? operatore in un'espressione concatenata, devi usare in tutte le proprietà perché se ti dimentichi di metterlo da qualche parte, avrai anche un errore. Sarà essere gentile se Groovy potrebbe rilevare il?. operatore in un'espressione e lo inietta nelle altre proprietà se vede l'operatore mancante. Quindi, se dovessi digitare questo

a? .b? .e.f? .g // Ho dimenticato di mettere il?. ? .n la "f" proprietà un .befg

Groovy potrebbe risolvere il problema con una vera e propria espressione di nulla-safe in questo modo:????

un .b .e .F .g

8

Non credo che la tua ipotesi fosse corretta.questo:

params.stringValue?.trim().replaceAll('aa', 'a') 

non significa:

if(params.stringValue is null) 
    dont proceed to trim() and replaceAll() 

Piuttosto significa:

if(params.stringValue is null) 
    skip trim() without complain but pass null to replaceAll() 

quindi è necessario dire:

params.stringValue?.trim()?.replaceAll('aa', 'a') 

Questo salterà sia trim() e replaceAll() se l'argomento in entrata è nullo.

8

L'assunzione è solo parzialmente corretta.

Il ? -operator non si rompe l'esecuzione in caso di null, esso blocchi richiamanti il ​​metodo corrente, e restituisce una null invece, motivo per cui è necessario anche per proteggere il lato destro della catena con ?