2015-06-12 16 views
5

Mein Projekt hat Code wie folgt aus:Chaining Null-Safe-Operator

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

Wir erwarten, dass, wenn params.stringValue null war, dass beidetrim() und replaceAll() nicht aufgerufen werden.

Allerdings erhielten wir eine NullPointerException auf dieser Zeile sagen, dass replaceAll() nicht auf ein Null-Objekt aufgerufen werden kann.

Wir hatten den Code zu ändern, so zu sein:

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

Warum Schnipsel ist der erste Code oben nicht funktionieren? Ist das ein Fehler in Groovy, der den Ausdruck auswertet, nachdem einmal eine Null gefunden wurde?

+0

Ich denke, es ist ein "Feature", anstatt ein Fehler (!) – Armand

Antwort

4

Es ist die Art und Weise Groovy arbeitet, in der Tat, und others gebissen hat:?.

println Buch .author .firstName .trim() concat ("groß").

...

Wenn ich diese Codezeile betrachte, dachte ich mir, dass ich sicher vor jeder hinterhältigen NullPointerException war. Wenn book, author oder firstName null sind, drucke ich einfach null und muss mich nicht um die concat() -Methode kümmern. Wenn die Methode trim() erfolgreich ist, ist es sinnlos, das Ergebnis für null zu schützen. Und da habe ich mich geirrt.

Es wurden mindestens this discussion gewesen, das zu ändern:

ein .b.c // Haben Sie den Fehler sehen? ;)

Ich werde eine NullPointerException bekommen. Ich meine, wenn Sie den Null-Safe benutzen? Operator in einem verketteten Ausdruck, müssen Sie in allen Eigenschaften verwenden, denn wenn Sie vergessen, irgendwo zu setzen, erhalten Sie auch einen Fehler. Es wird nett sein, wenn Groovy den?. Operator in einem Ausdruck, und es injiziert es in den anderen Eigenschaften, wenn es sieht der Operator fehlt. Also, wenn Sie dies eingeben würden

ein? .b? .e.f? .g // Ich vergesse, die?. ? .n die "f" Eigenschaft ein .befg

Groovy könnte fixieren Sie es mit einem echten Nullsicheren Ausdruck wie folgt aus:???

ein .B .E .f .g

8

Ich glaube nicht, dass Ihre Annahme richtig war.dies:

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

bedeutet nicht:

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

Es eher bedeutet:

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

so müssen Sie sagen:

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

Dies wird sowohl trim() überspringen und replaceAll(), wenn das eingehende Argument null ist.

8

Ihre Annahme ist nur teilweise richtig.

Die ? -Operator nicht bricht die Ausführung bei null, blockiert es die aktuelle Methode aufgerufen wird, und gibt ein null statt, weshalb es notwendig ist, auch die rechte Seite der Kette zu schützen mit ?