セーフナビゲーション演算子
セーフナビゲーション演算子 (?.) は、NullPointerException を回避するために使用され、Groovy (英語) 言語に由来します。通常、オブジェクトへの参照がある場合、オブジェクトのメソッドまたはプロパティにアクセスする前に、それが null ではないことを確認する必要がある場合があります。これを回避するために、セーフナビゲーションオペレーターは、例外をスローする代わりに、特定の null セーフ操作に対して null を返します。
複合式内の特定の null セーフ操作に対してセーフナビゲーション演算子が 詳細は複合式での Null セーフ操作を参照してください。 |
安全なプロパティとメソッドへのアクセス
次の例は、プロパティアクセスにセーフナビゲーション演算子 (?.) を使用する方法を示しています。
Java
Kotlin
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
// evaluates to "Smiljan"
String city = parser.parseExpression("placeOfBirth?.city") (1)
.getValue(context, tesla, String.class);
tesla.setPlaceOfBirth(null);
// evaluates to null - does not throw NullPointerException
city = parser.parseExpression("placeOfBirth?.city") (2)
.getValue(context, tesla, String.class);| 1 | null 以外の placeOfBirth プロパティでセーフナビゲーション演算子を使用する |
| 2 | null placeOfBirth プロパティでセーフナビゲーション演算子を使用する |
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val tesla = Inventor("Nikola Tesla", "Serbian")
tesla.setPlaceOfBirth(PlaceOfBirth("Smiljan"))
// evaluates to "Smiljan"
var city = parser.parseExpression("placeOfBirth?.city") (1)
.getValue(context, tesla, String::class.java)
tesla.setPlaceOfBirth(null)
// evaluates to null - does not throw NullPointerException
city = parser.parseExpression("placeOfBirth?.city") (2)
.getValue(context, tesla, String::class.java)| 1 | null 以外の placeOfBirth プロパティでセーフナビゲーション演算子を使用する |
| 2 | null placeOfBirth プロパティでセーフナビゲーション演算子を使用する |
セーフナビゲーション演算子は、オブジェクトのメソッド呼び出しにも適用されます。 例: |
安全なインデックスアクセス
Spring Framework 6.2 以降、Spring 式言語は、次の型の構造へのインデックス作成のための安全なナビゲーションをサポートしています。
次の例は、リストへのインデックス付けにセーフナビゲーション演算子 (?.[]) を使用する方法を示しています。
Java
Kotlin
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 | 非 null members リストに null セーフインデックス演算子を使用する |
| 2 | null members リストに null セーフインデックス演算子を使用する |
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 | 非 null members リストに null セーフインデックス演算子を使用する |
| 2 | null members リストに null セーフインデックス演算子を使用する |
安全なコレクションの選択と射影
null セーフ選択:
?.?null セーフ選択を最初に行う:
?.^null セーフ最後を選択:
?.$null セーフ射影:
?.!
次の例は、コレクション選択にセーフナビゲーション演算子 (?.?) を使用する方法を示しています。
Java
Kotlin
ExpressionParser parser = new SpelExpressionParser();
IEEE society = new IEEE();
StandardEvaluationContext context = new StandardEvaluationContext(society);
String expression = "members?.?[nationality == 'Serbian']"; (1)
// evaluates to [Inventor("Nikola Tesla")]
List<Inventor> list = (List<Inventor>) parser.parseExpression(expression)
.getValue(context);
society.members = null;
// evaluates to null - does not throw a NullPointerException
list = (List<Inventor>) parser.parseExpression(expression)
.getValue(context);| 1 | null の可能性がある members リストに対して null セーフ選択演算子を使用する |
val parser = SpelExpressionParser()
val society = IEEE()
val context = StandardEvaluationContext(society)
val expression = "members?.?[nationality == 'Serbian']" (1)
// evaluates to [Inventor("Nikola Tesla")]
var list = parser.parseExpression(expression)
.getValue(context) as List<Inventor>
society.members = null
// evaluates to null - does not throw a NullPointerException
list = parser.parseExpression(expression)
.getValue(context) as List<Inventor>| 1 | null の可能性がある members リストに対して null セーフ選択演算子を使用する |
次の例は、コレクション (?.^) に "null-safe select first" 演算子を使用する方法を示しています。
Java
Kotlin
ExpressionParser parser = new SpelExpressionParser();
IEEE society = new IEEE();
StandardEvaluationContext context = new StandardEvaluationContext(society);
String expression =
"members?.^[nationality == 'Serbian' || nationality == 'Idvor']"; (1)
// evaluates to Inventor("Nikola Tesla")
Inventor inventor = parser.parseExpression(expression)
.getValue(context, Inventor.class);
society.members = null;
// evaluates to null - does not throw a NullPointerException
inventor = parser.parseExpression(expression)
.getValue(context, Inventor.class);| 1 | null の可能性がある members リストに対して "null-safe select first" 演算子を使用する |
val parser = SpelExpressionParser()
val society = IEEE()
val context = StandardEvaluationContext(society)
val expression =
"members?.^[nationality == 'Serbian' || nationality == 'Idvor']" (1)
// evaluates to Inventor("Nikola Tesla")
var inventor = parser.parseExpression(expression)
.getValue(context, Inventor::class.java)
society.members = null
// evaluates to null - does not throw a NullPointerException
inventor = parser.parseExpression(expression)
.getValue(context, Inventor::class.java)| 1 | null の可能性がある members リストに対して "null-safe select first" 演算子を使用する |
次の例は、コレクション (?.$) に "null-safe select last" 演算子を使用する方法を示しています。
Java
Kotlin
ExpressionParser parser = new SpelExpressionParser();
IEEE society = new IEEE();
StandardEvaluationContext context = new StandardEvaluationContext(society);
String expression =
"members?.$[nationality == 'Serbian' || nationality == 'Idvor']"; (1)
// evaluates to Inventor("Pupin")
Inventor inventor = parser.parseExpression(expression)
.getValue(context, Inventor.class);
society.members = null;
// evaluates to null - does not throw a NullPointerException
inventor = parser.parseExpression(expression)
.getValue(context, Inventor.class);| 1 | null の可能性がある members リストに対して "null-safe select last" 演算子を使用する |
val parser = SpelExpressionParser()
val society = IEEE()
val context = StandardEvaluationContext(society)
val expression =
"members?.$[nationality == 'Serbian' || nationality == 'Idvor']" (1)
// evaluates to Inventor("Pupin")
var inventor = parser.parseExpression(expression)
.getValue(context, Inventor::class.java)
society.members = null
// evaluates to null - does not throw a NullPointerException
inventor = parser.parseExpression(expression)
.getValue(context, Inventor::class.java)| 1 | null の可能性がある members リストに対して "null-safe select last" 演算子を使用する |
次の例は、コレクション射影にセーフナビゲーション演算子 (?.!) を使用する方法を示しています。
Java
Kotlin
ExpressionParser parser = new SpelExpressionParser();
IEEE society = new IEEE();
StandardEvaluationContext context = new StandardEvaluationContext(society);
// evaluates to ["Smiljan", "Idvor"]
List placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") (1)
.getValue(context, List.class);
society.members = null;
// evaluates to null - does not throw a NullPointerException
placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") (2)
.getValue(context, List.class);| 1 | null 以外の members リストで null セーフな射影演算子を使用する |
| 2 | null members リストで null セーフ射影演算子を使用する |
val parser = SpelExpressionParser()
val society = IEEE()
val context = StandardEvaluationContext(society)
// evaluates to ["Smiljan", "Idvor"]
var placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") (1)
.getValue(context, List::class.java)
society.members = null
// evaluates to null - does not throw a NullPointerException
placesOfBirth = parser.parseExpression("members?.![placeOfBirth.city]") (2)
.getValue(context, List::class.java)| 1 | null 以外の members リストで null セーフな射影演算子を使用する |
| 2 | null members リストで null セーフ射影演算子を使用する |
複合式での Null セーフ操作
このセクションの冒頭で記述されていたように、複合式内の特定の null セーフ操作に対してセーフナビゲーション演算子が null と評価される場合でも、複合式の残りの部分は評価されます。これは、不要な NullPointerException を回避するために、複合式全体にセーフナビゲーション演算子を適用する必要があることを意味します。
式 #person?.address.city を指定すると、#person が null の場合、セーフナビゲーションオペレーター (?.) は、#person の address プロパティにアクセスしようとしたときに例外がスローされないことを保証します。ただし、#person?.address は null として評価されるため、null の city プロパティにアクセスしようとすると NullPointerException がスローされます。これに対処するには、#person?.address?.city のように複合式全体に null セーフナビゲーションを適用します。#person または #person?.address が null と評価される場合、その式は安全に null と評価されます。
次の例は、複合式内でコレクションに対して "null-safe select first" 演算子 (?.^) を使用し、null-safe プロパティアクセス (?.) と組み合わせて使用する方法を示しています。members が null の場合、"null-safe select first" 演算子 (members?.^[nationality == 'Serbian']) の結果は null に評価され、セーフナビゲーション演算子 (?.name) を追加使用することで、例外をスローする代わりに複合式全体が null に評価されるようになります。
Java
Kotlin
ExpressionParser parser = new SpelExpressionParser();
IEEE society = new IEEE();
StandardEvaluationContext context = new StandardEvaluationContext(society);
String expression = "members?.^[nationality == 'Serbian']?.name"; (1)
// evaluates to "Nikola Tesla"
String name = parser.parseExpression(expression)
.getValue(context, String.class);
society.members = null;
// evaluates to null - does not throw a NullPointerException
name = parser.parseExpression(expression)
.getValue(context, String.class);| 1 | 複合式内で "null-safe select first" および null-safe プロパティアクセス演算子を使用します。 |
val parser = SpelExpressionParser()
val society = IEEE()
val context = StandardEvaluationContext(society)
val expression = "members?.^[nationality == 'Serbian']?.name" (1)
// evaluates to "Nikola Tesla"
String name = parser.parseExpression(expression)
.getValue(context, String::class.java)
society.members = null
// evaluates to null - does not throw a NullPointerException
name = parser.parseExpression(expression)
.getValue(context, String::class.java)| 1 | 複合式内で "null-safe select first" および null-safe プロパティアクセス演算子を使用します。 |