diff --git a/rules/S4348/java/rule.adoc b/rules/S4348/java/rule.adoc index 15c0df637f..5f488012cb 100644 --- a/rules/S4348/java/rule.adoc +++ b/rules/S4348/java/rule.adoc @@ -1,16 +1,27 @@ == Why is this an issue? -There are two classes in the Java standard library that deal with iterations: ``++Iterable++`` and ``++Iterator++``. An ``++Iterable++`` represents a data structure that can be the target of the "for-each loop" statement, and an ``++Iterator++`` represents the state of an ongoing traversal. An ``++Iterable++`` is generally expected to support multiple traversals. +An `Iterable` should not implement the `Iterator` interface or return `this` as an `Iterator`. +The reason is that `Iterator` represents the iteration process itself, while `Iterable` represents the object we want to iterate over. -An ``++Iterator++`` that also implements ``++Iterable++`` by returning itself as its ``++iterator()++`` will not support multiple traversals since its state will be carried over. +The `Iterator` instance encapsulates state information of the iteration process, such as the current and next element. +Consequently, distinct iterations require distinct `Iterator` instances, for which `Iterable` provides the factory method `Iterable.iterator()`. +This rule raises an issue when the `Iterable.iterator()` of a class implementing both `Iterable` and `Iterator` returns `this`. -This rule raises an issue when the ``++iterator()++`` method of a class implementing both ``++Iterable++`` and ``++Iterator++`` returns ``++this++``. +=== What is the potential impact? +The `Iterable.iterator()` method returning the same `Iterator` instance many times would have the following effects: -=== Noncompliant code example +1. For subsequent iterations, e.g., two subsequent `for` loops with iterators over the same object, only the first one would iterate, and the others would do nothing. +2. For nested iterations over the same object, the different iteration processes would affect each other because they only have a common, shared state. -[source,java] +== How to fix it + +=== Code examples + +==== Noncompliant code example + +[source,java,diff-id=1,diff-type=noncompliant] ---- class FooIterator implements Iterator, Iterable { private Foo[] seq; @@ -31,16 +42,15 @@ class FooIterator implements Iterator, Iterable { } ---- +==== Compliant solution -=== Compliant solution - -[source,java] +[source,java,diff-id=1,diff-type=compliant] ---- class FooSequence implements Iterable { private Foo[] seq; public Iterator iterator() { - return new Iterator() { + return new Iterator() { // Compliant private int idx = 0; public boolean hasNext() { @@ -56,6 +66,14 @@ class FooSequence implements Iterable { } ---- +== Resources + +=== Documentation + +* https://docs.oracle.com/javase/7/docs/api/java/lang/Iterable.html[Java SE 7 API Specification: java.lang.Iterable] +* https://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html[Java SE 7 API Specification: java.util.Iterator] +* https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.14.2[Java 7 Language Specification: The enhanced for statement] (since Java 1.5) + ifdef::env-github,rspecator-view[] '''