gradle: fileCollection.plus () возвращает противоречащий интерфейс ArrayList

Aug 21 2020

gradle: fileCollection.plus () возвращает противоречащий интерфейс ArrayList.

def foo = files([]);  // foo: gradle FileCollection
println foo.class
foo = foo.plus(sourceSets.main.java.srcDirs);    // foo: java.util.ArrayList
println foo.class

Но он должен вернуть FileCollection:

https://docs.gradle.org/current/javadoc/org/gradle/api/file/FileCollection.html#plus-org.gradle.api.file.FileCollection-

Ответы

BjørnVester Aug 21 2020 at 10:45

plusМетод перегружен, и вы смотрите на неправильном.

API для FileCollection.plus, с которым вы связались , имеет подпись:

FileCollection plus (коллекция FileCollection)

Возвращает FileCollection, который содержит объединение этой коллекции и данной коллекции. Возвращенная коллекция является активной и отслеживает изменения в обеих исходных коллекциях.

Но вы передаете в ArrayListкачестве параметра. An ArrayListне является FileCollection.

Однако a FileCollectionтакже является an Iterable, поэтому на самом деле вы вызываете стандартный метод Groovy Interable.plus с такой сигнатурой:

публичная коллекция плюс (итерационное право)

Создайте коллекцию как объединение двух итераций. Если левая итерация - это Set, то возвращенная коллекция будет Set, в противном случае - списком. Эта операция всегда будет создавать новый объект для результата, в то время как операнды остаются неизменными.

Поскольку «левая» итерация не является Set(это FileCollection), вы получаете возврат List, а Groovy просто использует ArrayListв реализации.