Modify rule S4348: reworked rule description for LaYC format (#2873)

This commit is contained in:
Marco Kaufmann 2023-08-15 17:18:52 +02:00 committed by GitHub
parent 76c34b093a
commit 74437e0a15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,16 +1,27 @@
== Why is this an issue?
There are two classes in the Java standard library that deal with iterations: ``++Iterable<T>++`` and ``++Iterator<T>++``. An ``++Iterable<T>++`` represents a data structure that can be the target of the "for-each loop" statement, and an ``++Iterator<T>++`` represents the state of an ongoing traversal. An ``++Iterable<T>++`` 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<T>++`` that also implements ``++Iterable<t>++`` 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<T>++`` and ``++Iterator<t>++`` 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<Foo>, Iterable<Foo> {
private Foo[] seq;
@ -31,16 +42,15 @@ class FooIterator implements Iterator<Foo>, Iterable<Foo> {
}
----
==== Compliant solution
=== Compliant solution
[source,java]
[source,java,diff-id=1,diff-type=compliant]
----
class FooSequence implements Iterable<Foo> {
private Foo[] seq;
public Iterator<Foo> iterator() {
return new Iterator<Foo>() {
return new Iterator<Foo>() { // Compliant
private int idx = 0;
public boolean hasNext() {
@ -56,6 +66,14 @@ class FooSequence implements Iterable<Foo> {
}
----
== 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[]
'''