セーフナビゲーション演算子
セーフナビゲーション演算子 (?
) は、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 プロパティでセーフナビゲーション演算子を使用する |
セーフナビゲーション演算子は、オブジェクトのメソッド呼び出しにも適用されます。 例: |
安全なコレクションの選択と射影
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 プロパティアクセス演算子を使用します。 |