diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java index a2f1df38cd7..cf62dfd3a3a 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java @@ -44,8 +44,21 @@ import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** - * An Indexer can index into some proceeding structure to access a particular piece of it. - *

Supported structures are: strings / collections (lists/sets) / arrays. + * An {@code Indexer} can index into some proceeding structure to access a + * particular element of the structure. + * + *

Numerical index values are zero-based, such as when accessing the + * nth element of an array in Java. + * + *

Supported Structures

+ * + * * * @author Andy Clement * @author Phillip Webb @@ -58,6 +71,9 @@ public class Indexer extends SpelNodeImpl { private enum IndexedType {ARRAY, LIST, MAP, STRING, OBJECT} + @Nullable + private IndexedType indexedType; + // These fields are used when the indexer is being used as a property read accessor. // If the name and target type match these cached values then the cachedReadAccessor // is used to read the property. If they do not match, the correct accessor is @@ -86,12 +102,13 @@ public class Indexer extends SpelNodeImpl { @Nullable private PropertyAccessor cachedWriteAccessor; - @Nullable - private IndexedType indexedType; - - public Indexer(int startPos, int endPos, SpelNodeImpl expr) { - super(startPos, endPos, expr); + /** + * Create an {@code Indexer} with the given start position, end position, and + * index expression. + */ + public Indexer(int startPos, int endPos, SpelNodeImpl indexExpression) { + super(startPos, endPos, indexExpression); } @@ -146,6 +163,7 @@ public class Indexer extends SpelNodeImpl { if (target == null) { throw new SpelEvaluationException(getStartPosition(), SpelMessage.CANNOT_INDEX_INTO_NULL_VALUE); } + // At this point, we need a TypeDescriptor for a non-null target object Assert.state(targetDescriptor != null, "No type descriptor"); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java index d3f65e31fc6..5feed1c9044 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java @@ -62,7 +62,6 @@ class IndexingTests { assertThat(expression.getValue(this)).isEqualTo(4); } - @Test @SuppressWarnings("unchecked") void indexIntoGenericPropertyContainingMap() { @@ -302,7 +301,7 @@ class IndexingTests { @Test void indexIntoGenericPropertyContainingArray() { - String[] property = new String[] { "bar" }; + String[] property = { "bar" }; this.property = property; SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("property"); @@ -357,17 +356,17 @@ class IndexingTests { @Test @SuppressWarnings("unchecked") - void testListOfScalar() { + void listOfScalars() { listOfScalarNotGeneric = new ArrayList(1); listOfScalarNotGeneric.add("5"); SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("listOfScalarNotGeneric[0]"); - assertThat(expression.getValue(this, Integer.class)).isEqualTo(Integer.valueOf(5)); + assertThat(expression.getValue(this, Integer.class)).isEqualTo(5); } @Test @SuppressWarnings("unchecked") - void testListsOfMap() { + void listOfMaps() { listOfMapsNotGeneric = new ArrayList(); Map map = new HashMap(); map.put("fruit", "apple");