[
https://issues.apache.org/jira/browse/GROOVY-11818?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Eric Milles updated GROOVY-11818:
---------------------------------
Language: groovy
> For loop variable reference in anonymous classes yields unexpected results
> --------------------------------------------------------------------------
>
> Key: GROOVY-11818
> URL: https://issues.apache.org/jira/browse/GROOVY-11818
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 3.0.25, 4.0.29
> Reporter: James Daugherty
> Priority: Minor
>
> I'm not sure if this is really a bug or design decision of Groovy that could
> be improved.
> Given this java code:
> {code:java}
> import java.util.*;
> import java.util.stream.*;
> class MyCommand {
> String filename;
> MyCommand(String filename) { this.filename = filename; }
> String getFilename() { return filename; }
> }
> interface MyFile {
> String getFilename();
> }
> List<MyCommand> commands = List.of(
> new MyCommand("testing1"),
> new MyCommand("testing2")
> );
> List<MyFile> files = new ArrayList<>();
> for (MyCommand cmd : commands) {
> MyFile file = new MyFile() {
> @Override
> public String getFilename() {
> return cmd.getFilename();
> }
> };
> files.add(file);
> }
> List<String> filenames = files.stream()
> .map(MyFile::getFilename)
> .collect(Collectors.toList());
> filenames
> {code}
> You can execute this code in jshell, and it will output:
> {code:java}
> | created class MyCommand
> | created interface MyFile
> commands ==> [MyCommand@34c45dca, MyCommand@52cc8049]
> files ==> []
> filenames ==> [testing1, testing2]
> filenames ==> [testing1, testing2] {code}
> But the equivalent in groovy code:
> {code:java}
> class MyCommand {
> String filename
> }
> interface MyFile {
> String getFilename()
> }
> List<MyCommand> commands = [new MyCommand(filename: 'testing1'),new
> MyCommand(filename: 'testing2')]
> List<MyFile> files = []
> for(MyCommand cmd in commands) {
> MyFile file = new MyFile() {
> String getFilename() {
> cmd.filename
> }
> }
> files.add(file)
> }
> files.collect{ it.filename }{code}
> will output
> {code:java}
> [testing2, testing2] {code}
> in Groovy 3.0.25 & 4.0.29 (tested in GroovyConsole). Adding a local
> variable to store the filename for that loop will fix the groovy code to
> return the same value as the Java equivalent. It seems the `cmd` variable is
> being reused on each iteration instead of creating a new reference. This
> causes code inside of the for loop for previous iterations to be updated to
> the new iteration value - which is inconsistent with Java's behavior.
> Note: using the closure iteration syntax (.each \{ }) does not have this same
> behavior as Java. Since both Java & the closure iteration syntax produce the
> same result, I think the for loop difference should be considered a bug in
> Groovy.
>
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)