Ruiqi Dong created COLLECTIONS-890:
--------------------------------------
Summary: TransformIterator documents null transformers as
pass-through, but next() throws NullPointerException
Key: COLLECTIONS-890
URL: https://issues.apache.org/jira/browse/COLLECTIONS-890
Project: Commons Collections
Issue Type: Bug
Components: Iterator
Reporter: Ruiqi Dong
*Summary*
`TransformIterator` documents the same contract in three places:
- constructor: null transformer means elements will not be transformed
- `next()`: null transformer means the original element is returned directly
- `setTransformer(...)`: null transformer is a no-op transformer
The implementation does not honor that contract. `next()` always calls
`transformer.apply(...)`, so a null transformer causes an immediate
`NullPointerException`.
*Affected code*
File:
`src/main/java/org/apache/commons/collections4/iterators/TransformIterator.java`
{code:java}
public TransformIterator(final Iterator<? extends I> iterator,
final Transformer<? super I, ? extends O> transformer)
{
this.iterator = iterator;
this.transformer = transformer;
}
@Override
public O next() {
return transform(iterator.next());
}
protected O transform(final I source) {
return transformer.apply(source);
} {code}
The same class also states:
{code:java}
// constructor Javadoc
// If the given transformer is null, then objects will not be transformed.
// next() Javadoc
// If the transformer is null, no transformation occurs and the object
// from the iterator is returned directly.
// setTransformer(...) Javadoc
// A null transformer is a no-op transformer. {code}
*Reproducer*
Add the following test to
`src/test/java/org/apache/commons/collections4/iterators/TransformIteratorTest.java`:
{code:java}
@Test
void testNullTransformerActsAsPassThrough() {
final TransformIterator<Integer, Integer> iterator =
new TransformIterator<>(Arrays.asList(1, 2).iterator(), null);
assertEquals(Integer.valueOf(1), iterator.next());
assertEquals(Integer.valueOf(2), iterator.next());
} {code}
Run:
{code:java}
mvn -q
-Dtest=org.apache.commons.collections4.iterators.TransformIteratorTest#testNullTransformerActsAsPassThrough
test {code}
*Observed behavior*
{code:java}
java.lang.NullPointerException:
Cannot invoke "org.apache.commons.collections4.Transformer.apply(Object)"
because "this.transformer" is null {code}
*Expected behavior*
When the transformer is null, the iterator should behave as an identity
transform and return the original elements unchanged.
This is not just an undocumented corner case. The public Javadoc explicitly
promises null-as-pass-through behavior, but the implementation unconditionally
dereferences the transformer. Callers following the documented contract get a
runtime failure instead of the advertised semantics.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)