@@ -7,6 +7,9 @@ language. Typically, when you have a reference to an object, you might need to v
7
7
that it is not `null` before accessing methods or properties of the object. To avoid
8
8
this, the safe navigation operator returns `null` instead of throwing an exception.
9
9
10
+ [[expressions-operator-safe-navigation-property-access]]
11
+ == Safe Property and Method Access
12
+
10
13
The following example shows how to use the safe navigation operator for property access
11
14
(`?.`).
12
15
@@ -59,3 +62,224 @@ Kotlin::
59
62
<2> Use safe navigation operator on null `placeOfBirth` property
60
63
======
61
64
65
+ [NOTE]
66
+ ====
67
+ The safe navigation operator also applies to method invocations on an object.
68
+
69
+ For example, the expression `#calculator?.max(4, 2)` evaluates to `null` if the
70
+ `#calculator` variable has not been configured in the context. Otherwise, the
71
+ `max(int, int)` method will be invoked on the `#calculator`.
72
+ ====
73
+
74
+
75
+ [[expressions-operator-safe-navigation-selection-and-projection]]
76
+ == Safe Collection Selection and Projection
77
+
78
+ The Spring Expression Language supports safe navigation for
79
+ xref:core/expressions/language-ref/collection-selection.adoc[collection selection] and
80
+ xref:core/expressions/language-ref/collection-projection.adoc[collection projection] via
81
+ the following operators.
82
+
83
+ * null-safe selection: `?.?`
84
+ * null-safe select first: `?.^`
85
+ * null-safe select last: `?.$`
86
+ * null-safe projection: `?.!`
87
+
88
+ The following example shows how to use the safe navigation operator for collection
89
+ selection (`?.?`).
90
+
91
+ [tabs]
92
+ ======
93
+ Java::
94
+ +
95
+ [source,java,indent=0,subs="verbatim,quotes",role="primary"]
96
+ ----
97
+ ExpressionParser parser = new SpelExpressionParser();
98
+ IEEE society = new IEEE();
99
+ StandardEvaluationContext context = new StandardEvaluationContext(society);
100
+ String expression = "members?.?[nationality == 'Serbian']"; // <1>
101
+
102
+ // evaluates to [Inventor("Nikola Tesla")]
103
+ List<Inventor> list = (List<Inventor>) parser.parseExpression(expression)
104
+ .getValue(context);
105
+
106
+ society.members = null;
107
+
108
+ // evaluates to null - does not throw a NullPointerException
109
+ list = (List<Inventor>) parser.parseExpression(expression)
110
+ .getValue(context);
111
+ ----
112
+ <1> Use null-safe selection operator on potentially null `members` list
113
+
114
+ Kotlin::
115
+ +
116
+ [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
117
+ ----
118
+ val parser = SpelExpressionParser()
119
+ val society = IEEE()
120
+ val context = StandardEvaluationContext(society)
121
+ val expression = "members?.?[nationality == 'Serbian']" // <1>
122
+
123
+ // evaluates to [Inventor("Nikola Tesla")]
124
+ var list = parser.parseExpression(expression)
125
+ .getValue(context) as List<Inventor>
126
+
127
+ society.members = null
128
+
129
+ // evaluates to null - does not throw a NullPointerException
130
+ list = parser.parseExpression(expression)
131
+ .getValue(context) as List<Inventor>
132
+ ----
133
+ <1> Use null-safe selection operator on potentially null `members` list
134
+ ======
135
+
136
+ The following example shows how to use the "null-safe select first" operator for
137
+ collections (`?.^`).
138
+
139
+ [tabs]
140
+ ======
141
+ Java::
142
+ +
143
+ [source,java,indent=0,subs="verbatim,quotes",role="primary"]
144
+ ----
145
+ ExpressionParser parser = new SpelExpressionParser();
146
+ IEEE society = new IEEE();
147
+ StandardEvaluationContext context = new StandardEvaluationContext(society);
148
+ String expression =
149
+ "members?.^[nationality == 'Serbian' || nationality == 'Idvor']"; // <1>
150
+
151
+ // evaluates to Inventor("Nikola Tesla")
152
+ Inventor inventor = parser.parseExpression(expression)
153
+ .getValue(context, Inventor.class);
154
+
155
+ society.members = null;
156
+
157
+ // evaluates to null - does not throw a NullPointerException
158
+ inventor = parser.parseExpression(expression)
159
+ .getValue(context, Inventor.class);
160
+ ----
161
+ <1> Use "null-safe select first" operator on potentially null `members` list
162
+
163
+ Kotlin::
164
+ +
165
+ [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
166
+ ----
167
+ val parser = SpelExpressionParser()
168
+ val society = IEEE()
169
+ val context = StandardEvaluationContext(society)
170
+ val expression =
171
+ "members?.^[nationality == 'Serbian' || nationality == 'Idvor']" // <1>
172
+
173
+ // evaluates to Inventor("Nikola Tesla")
174
+ var inventor = parser.parseExpression(expression)
175
+ .getValue(context, Inventor::class.java)
176
+
177
+ society.members = null
178
+
179
+ // evaluates to null - does not throw a NullPointerException
180
+ inventor = parser.parseExpression(expression)
181
+ .getValue(context, Inventor::class.java)
182
+ ----
183
+ <1> Use "null-safe select first" operator on potentially null `members` list
184
+ ======
185
+
186
+
187
+ The following example shows how to use the "null-safe select last" operator for
188
+ collections (`?.$`).
189
+
190
+ [tabs]
191
+ ======
192
+ Java::
193
+ +
194
+ [source,java,indent=0,subs="verbatim,quotes",role="primary"]
195
+ ----
196
+ ExpressionParser parser = new SpelExpressionParser();
197
+ IEEE society = new IEEE();
198
+ StandardEvaluationContext context = new StandardEvaluationContext(society);
199
+ String expression =
200
+ "members?.$[nationality == 'Serbian' || nationality == 'Idvor']"; // <1>
201
+
202
+ // evaluates to Inventor("Pupin")
203
+ Inventor inventor = parser.parseExpression(expression)
204
+ .getValue(context, Inventor.class);
205
+
206
+ society.members = null;
207
+
208
+ // evaluates to null - does not throw a NullPointerException
209
+ inventor = parser.parseExpression(expression)
210
+ .getValue(context, Inventor.class);
211
+ ----
212
+ <1> Use "null-safe select last" operator on potentially null `members` list
213
+
214
+ Kotlin::
215
+ +
216
+ [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
217
+ ----
218
+ val parser = SpelExpressionParser()
219
+ val society = IEEE()
220
+ val context = StandardEvaluationContext(society)
221
+ val expression =
222
+ "members?.$[nationality == 'Serbian' || nationality == 'Idvor']" // <1>
223
+
224
+ // evaluates to Inventor("Pupin")
225
+ var inventor = parser.parseExpression(expression)
226
+ .getValue(context, Inventor::class.java)
227
+
228
+ society.members = null
229
+
230
+ // evaluates to null - does not throw a NullPointerException
231
+ inventor = parser.parseExpression(expression)
232
+ .getValue(context, Inventor::class.java)
233
+ ----
234
+ <1> Use "null-safe select last" operator on potentially null `members` list
235
+ ======
236
+
237
+ The following example shows how to use the safe navigation operator for collection
238
+ projection (`?.!`).
239
+
240
+ [tabs]
241
+ ======
242
+ Java::
243
+ +
244
+ [source,java,indent=0,subs="verbatim,quotes",role="primary"]
245
+ ----
246
+ ExpressionParser parser = new SpelExpressionParser();
247
+ IEEE society = new IEEE();
248
+ StandardEvaluationContext context = new StandardEvaluationContext(society);
249
+
250
+ // evaluates to ["Smiljan", "Idvor"]
251
+ List placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") // <1>
252
+ .getValue(context, List.class);
253
+
254
+ society.members = null;
255
+
256
+ // evaluates to null - does not throw a NullPointerException
257
+ placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") // <2>
258
+ .getValue(context, List.class);
259
+ ----
260
+ <1> Use null-safe projection operator on non-null `members` list
261
+ <2> Use null-safe projection operator on null `members` list
262
+
263
+ Kotlin::
264
+ +
265
+ [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
266
+ ----
267
+ val parser = SpelExpressionParser()
268
+ val society = IEEE()
269
+ val context = StandardEvaluationContext(society)
270
+
271
+ // evaluates to ["Smiljan", "Idvor"]
272
+ var placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") // <1>
273
+ .getValue(context, List::class.java)
274
+
275
+ society.members = null
276
+
277
+ // evaluates to null - does not throw a NullPointerException
278
+ placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") // <2>
279
+ .getValue(context, List::class.java)
280
+ ----
281
+ <1> Use null-safe projection operator on non-null `members` list
282
+ <2> Use null-safe projection operator on null `members` list
283
+ ======
284
+
285
+
0 commit comments