parent
38c473fd05
commit
218a148898
|
|
@ -1,7 +1,7 @@
|
||||||
[[expressions-operator-safe-navigation]]
|
[[expressions-operator-safe-navigation]]
|
||||||
= Safe Navigation Operator
|
= Safe Navigation Operator
|
||||||
|
|
||||||
The safe navigation operator (`?`) is used to avoid a `NullPointerException` and comes
|
The safe navigation operator (`?.`) is used to avoid a `NullPointerException` and comes
|
||||||
from the https://www.groovy-lang.org/operators.html#_safe_navigation_operator[Groovy]
|
from the https://www.groovy-lang.org/operators.html#_safe_navigation_operator[Groovy]
|
||||||
language. Typically, when you have a reference to an object, you might need to verify
|
language. Typically, when you have a reference to an object, you might need to verify
|
||||||
that it is not `null` before accessing methods or properties of the object. To avoid
|
that it is not `null` before accessing methods or properties of the object. To avoid
|
||||||
|
|
@ -81,6 +81,64 @@ For example, the expression `#calculator?.max(4, 2)` evaluates to `null` if the
|
||||||
`max(int, int)` method will be invoked on the `#calculator`.
|
`max(int, int)` method will be invoked on the `#calculator`.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[expressions-operator-safe-navigation-indexing]]
|
||||||
|
== Safe Index Access
|
||||||
|
|
||||||
|
Since Spring Framework 6.2, the Spring Expression Language supports safe navigation for
|
||||||
|
indexing into the following types of structures.
|
||||||
|
|
||||||
|
* xref:core/expressions/language-ref/properties-arrays.adoc#expressions-indexing-arrays-and-collections[arrays and collections]
|
||||||
|
* xref:core/expressions/language-ref/properties-arrays.adoc#expressions-indexing-strings[strings]
|
||||||
|
* xref:core/expressions/language-ref/properties-arrays.adoc#expressions-indexing-maps[maps]
|
||||||
|
* xref:core/expressions/language-ref/properties-arrays.adoc#expressions-indexing-objects[objects]
|
||||||
|
|
||||||
|
The following example shows how to use the safe navigation operator for indexing into
|
||||||
|
a list (`?.[]`).
|
||||||
|
|
||||||
|
[tabs]
|
||||||
|
======
|
||||||
|
Java::
|
||||||
|
+
|
||||||
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||||
|
----
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
IEEE society = new IEEE();
|
||||||
|
EvaluationContext context = new StandardEvaluationContext(society);
|
||||||
|
|
||||||
|
// evaluates to Inventor("Nikola Tesla")
|
||||||
|
Inventor inventor = parser.parseExpression("members?.[0]") // <1>
|
||||||
|
.getValue(context, Inventor.class);
|
||||||
|
|
||||||
|
society.members = null;
|
||||||
|
|
||||||
|
// evaluates to null - does not throw an exception
|
||||||
|
inventor = parser.parseExpression("members?.[0]") // <2>
|
||||||
|
.getValue(context, Inventor.class);
|
||||||
|
----
|
||||||
|
<1> Use null-safe index operator on a non-null `members` list
|
||||||
|
<2> Use null-safe index operator on a null `members` list
|
||||||
|
|
||||||
|
Kotlin::
|
||||||
|
+
|
||||||
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||||
|
----
|
||||||
|
val parser = SpelExpressionParser()
|
||||||
|
val society = IEEE()
|
||||||
|
val context = StandardEvaluationContext(society)
|
||||||
|
|
||||||
|
// evaluates to Inventor("Nikola Tesla")
|
||||||
|
var inventor = parser.parseExpression("members?.[0]") // <1>
|
||||||
|
.getValue(context, Inventor::class.java)
|
||||||
|
|
||||||
|
society.members = null
|
||||||
|
|
||||||
|
// evaluates to null - does not throw an exception
|
||||||
|
inventor = parser.parseExpression("members?.[0]") // <2>
|
||||||
|
.getValue(context, Inventor::class.java)
|
||||||
|
----
|
||||||
|
<1> Use null-safe index operator on a non-null `members` list
|
||||||
|
<2> Use null-safe index operator on a null `members` list
|
||||||
|
======
|
||||||
|
|
||||||
[[expressions-operator-safe-navigation-selection-and-projection]]
|
[[expressions-operator-safe-navigation-selection-and-projection]]
|
||||||
== Safe Collection Selection and Projection
|
== Safe Collection Selection and Projection
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ into various structures.
|
||||||
NOTE: Numerical index values are zero-based, such as when accessing the n^th^ element of
|
NOTE: Numerical index values are zero-based, such as when accessing the n^th^ element of
|
||||||
an array in Java.
|
an array in Java.
|
||||||
|
|
||||||
|
TIP: See the xref:core/expressions/language-ref/operator-safe-navigation.adoc[Safe Navigation Operator]
|
||||||
|
section for details on how to navigate object graphs and index into various structures
|
||||||
|
using the null-safe operator.
|
||||||
|
|
||||||
[[expressions-property-navigation]]
|
[[expressions-property-navigation]]
|
||||||
== Property Navigation
|
== Property Navigation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,13 @@ import org.springframework.util.ReflectionUtils;
|
||||||
* <li>Objects: the property with the specified name</li>
|
* <li>Objects: the property with the specified name</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* <h3>Null-safe Indexing</h3>
|
||||||
|
*
|
||||||
|
* <p>As of Spring Framework 6.2, null-safe indexing is supported via the {@code '?.'}
|
||||||
|
* operator. For example, {@code 'colors?.[0]'} will evaluate to {@code null} if
|
||||||
|
* {@code colors} is {@code null} and will otherwise evaluate to the 0<sup>th</sup>
|
||||||
|
* color.
|
||||||
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
|
|
||||||
|
|
@ -688,6 +688,24 @@ class SpelDocumentationTests extends AbstractExpressionTests {
|
||||||
assertThat(city).isNull();
|
assertThat(city).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nullSafeIndexing() {
|
||||||
|
IEEE society = new IEEE();
|
||||||
|
EvaluationContext context = new StandardEvaluationContext(society);
|
||||||
|
|
||||||
|
// evaluates to Inventor("Nikola Tesla")
|
||||||
|
Inventor inventor = parser.parseExpression("members?.[0]") // <1>
|
||||||
|
.getValue(context, Inventor.class);
|
||||||
|
assertThat(inventor).extracting(Inventor::getName).isEqualTo("Nikola Tesla");
|
||||||
|
|
||||||
|
society.members = null;
|
||||||
|
|
||||||
|
// evaluates to null - does not throw an Exception
|
||||||
|
inventor = parser.parseExpression("members?.[0]") // <2>
|
||||||
|
.getValue(context, Inventor.class);
|
||||||
|
assertThat(inventor).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
void nullSafeSelection() {
|
void nullSafeSelection() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue