RFR: 8301604: Replace Collections.unmodifiableList with List.of
Nir Lisker
nlisker at openjdk.org
Wed Feb 1 14:52:06 UTC 2023
On Thu, 26 Jan 2023 05:30:56 GMT, Glavo <duke at openjdk.org> wrote:
> `List.of` is cleaner, and can slightly reduce the memory footprint for lists of one or two elements.
>
> Because `List.of` can only store non-null elements, I have only replaced a few usage.
>
> Can someone open an Issue on JBS for me?
### FileChooser
`List.of` and `List.copyOf` already check for a `null` argument and `null` elements. This means that `validateArgs` only needs to check the `length` of `extensions` and for an empty element. Since the only difference between the constructors is taking an array vs. taking a list, once a list is created from the array, the array constructor can call the list constructor.
I suggest the following refactoring:
public ExtensionFilter(String description, String... extensions) {
this(description, List.of(extensions));
}
public ExtensionFilter(String description, List<String> extensions) {
var extensionsList = List.copyOf(extensions);
validateArgs(description, extensionsList);
this.description = description;
this.extensions = extensionsList;
}
Note that `List.copyOf` will not create another copy if it was called from the array constructor that already created an unmodifiable `List.of`.
Now validation can be reduced to
private static void validateArgs(String description, List<String> extensions) {
Objects.requireNonNull(description, "Description must not be null");
if (description.isEmpty()) {
throw new IllegalArgumentException("Description must not be empty");
}
if (extensions.isEmpty()) {
throw new IllegalArgumentException("At least one extension must be defined");
}
for (String extension : extensions) {
if (extension.isEmpty()) {
throw new IllegalArgumentException("Extension must not be empty");
}
}
}
Aditionally, please add empty lines after the class declarations of `FileChooser` and `ExtensionFilter`.
Also please correct the typo in `getTracks`: "The returned <code>List</code> **is** unmodifiable."
modules/javafx.graphics/src/main/java/com/sun/javafx/iio/common/ImageDescriptor.java line 41:
> 39: this.extensions = List.of(extensions);
> 40: this.signatures = List.of(signatures);
> 41: this.mimeSubtypes = List.of(mimeSubtypes);
While this is not equivalent since changing the backing array will not change the resulting list anymore, I would consider the old code a bug and this the correct fix.
Note that in `FileChooser` care is taken to create a copy of the supplied array before using it to create a list.
Additionally, care must be taken that all the callers don't have `null` elements in the arrays they pass. I checked it and it's fine (and should probably be disallowed, which is good now).
By the way, this class should be a `record`, and all its subtypes, which are not really subtypes but just configured instances, should be modified accordingly. This is out of scope though.
modules/javafx.media/src/main/java/com/sun/media/jfxmedia/Media.java line 100:
> 98: returnValue = null;
> 99: } else {
> 100: returnValue = List.copyOf(tracks);
This is fine because `addTrack` checks for `null` elements.
modules/javafx.media/src/main/java/com/sun/media/jfxmedia/Media.java line 103:
> 101: }
> 102: }
> 103: return returnValue;
This method can be reduced to
public List<Track> getTracks() {
synchronized (tracks) {
return tracks.isEmpty() ? null : List.copyOf(tracks);
}
}
though I find it highly questionable that it returns `null` for an empty list instead of just an empty list. There are 2 use cases of this method and both would do better with just an empty list.
-------------
Changes requested by nlisker (Reviewer).
PR: https://git.openjdk.org/jfx/pull/1012
More information about the openjfx-dev
mailing list