You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2024/02/06 18:11:05 UTC

(sis) branch geoapi-4.0 updated (1a7a2aac78 -> 938b35b5e4)

This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a change to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


    from 1a7a2aac78 Post-merge automatic import reorganization.
     new f75d3fb406 Partial cleanup of compiler warnings: - Resolve "unchecked" warnings with an internal `Unsafe` class. - "ThisEscapedInObjectConstruction" replaced by "this-escape". - Remove a few @SuppressWarnings("null") which were too broad.
     new 76f2e5a33f Move in `JDK19` internal class the calls to methods that will be replaced by Java 19 method calls when SIS will be allowed to use it.
     new 938b35b5e4 Deprecate `ArgumentChecks` methods that are replaced by Java 9 methods: - `ensureValidIndex`, replaced by `Objects.checkIndex`. - `ensureValidIndexRange`, replaced by `Objects.checkFromToIndex`.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../sis/buildtools/coding/ReorganizeImports.java   |   5 +-
 .../main/org/apache/sis/console/SIS.java           |   2 +-
 .../main/org/apache/sis/coverage/Category.java     |   1 +
 .../main/org/apache/sis/coverage/CategoryList.java |   4 +-
 .../org/apache/sis/coverage/CoverageCombiner.java  |   2 -
 .../org/apache/sis/coverage/SampleDimension.java   |   6 +-
 .../apache/sis/coverage/grid/DefaultEvaluator.java |   6 +-
 .../sis/coverage/grid/DimensionalityReduction.java |  10 +-
 .../apache/sis/coverage/grid/DomainLinearizer.java |   2 -
 .../sis/coverage/grid/GridCoordinatesView.java     |   5 +-
 .../org/apache/sis/coverage/grid/GridExtent.java   |  21 ++--
 .../org/apache/sis/coverage/grid/GridGeometry.java |   4 +-
 .../apache/sis/feature/CharacteristicTypeMap.java  |   9 +-
 .../apache/sis/feature/DefaultAttributeType.java   |   2 +-
 .../org/apache/sis/feature/DefaultFeatureType.java |   2 +-
 .../main/org/apache/sis/image/ComputedTiles.java   |   1 -
 .../org/apache/sis/index/tree/NodeIterator.java    |   1 -
 .../sis/image/processing/isoline/StepsViewer.java  |   1 -
 .../org/apache/sis/index/tree/PointTreeTest.java   |   6 +-
 .../apache/sis/metadata/ModifiableMetadata.java    |   3 +-
 .../org/apache/sis/metadata/PropertyAccessor.java  |  30 +++---
 .../main/org/apache/sis/metadata/TreeNode.java     |   8 +-
 .../org/apache/sis/metadata/internal/Merger.java   |  15 +--
 .../sis/metadata/iso/extent/DefaultExtent.java     |   4 +-
 .../org/apache/sis/util/iso/DefaultRecordType.java |   6 +-
 .../org/apache/sis/util/iso/RecordDefinition.java  |   5 +-
 .../main/org/apache/sis/util/iso/Types.java        |   5 +-
 .../main/org/apache/sis/xml/bind/Context.java      |   1 -
 .../apache/sis/xml/bind/IdentifierMapAdapter.java  |   7 +-
 .../apache/sis/xml/bind/lan/LocaleAndCharset.java  |  13 +--
 .../apache/sis/metadata/iso/MarshallingTest.java   |   1 -
 .../sis/profile/japan/netcdf/FactoryForUCAR.java   |   2 +
 .../referencing/gazetteer/FinalLocationType.java   |   6 +-
 .../sis/referencing/gazetteer/LocationFormat.java  |   2 +-
 .../gazetteer/ReferencingByIdentifiers.java        |   2 +-
 .../org/apache/sis/geometry/ArrayEnvelope.java     |  18 ++--
 .../org/apache/sis/geometry/GeneralEnvelope.java   |  22 +----
 .../main/org/apache/sis/geometry/SubEnvelope.java  |  14 +--
 .../apache/sis/geometry/WraparoundInEnvelope.java  |   1 -
 .../main/org/apache/sis/io/wkt/Warnings.java       |   6 +-
 .../org/apache/sis/parameter/ParameterFormat.java  |   5 +-
 .../apache/sis/parameter/ParameterValueList.java   |  17 ++--
 .../main/org/apache/sis/referencing/CRS.java       |   3 +-
 .../referencing/factory/sql/EPSGCodeFinder.java    |  14 +--
 .../factory/sql/InstallationScriptProvider.java    |   1 -
 .../operation/builder/LinearTransformBuilder.java  |   4 +-
 .../referencing/operation/gridded/GridGroup.java   |   5 +-
 .../referencing/operation/gridded/LoadedGrid.java  |   5 +-
 .../sis/referencing/operation/matrix/Matrices.java |   3 +-
 .../referencing/operation/matrix/MatrixSIS.java    |  12 +--
 .../sis/referencing/operation/provider/NTv2.java   |   4 +-
 .../operation/transform/ConcatenatedTransform.java |   2 +
 .../referencing/util/GeodeticObjectBuilder.java    |   4 +-
 .../referencing/CC_GeneralOperationParameter.java  |   9 +-
 .../referencing/CC_OperationParameterGroup.java    |   6 +-
 .../org/apache/sis/storage/geotiff/DataSubset.java |   1 +
 .../sis/storage/geotiff/ImageFileDirectory.java    |  12 +--
 .../sis/storage/geotiff/writer/TileMatrix.java     |   1 -
 .../apache/sis/storage/netcdf/base/Variable.java   |   4 +-
 .../sis/storage/netcdf/classic/ChannelDecoder.java |   6 +-
 .../sis/storage/netcdf/ucar/DecoderWrapper.java    |   4 +-
 .../apache/sis/storage/sql/SQLStoreProvider.java   |   7 +-
 .../sis/storage/sql/feature/FeatureIterator.java   |   1 +
 .../org/apache/sis/storage/sql/feature/Table.java  |   5 +-
 .../sis/storage/xml/stream/StaxStreamReader.java   |   3 +-
 .../sis/storage/xml/stream/StaxStreamWriter.java   |   1 -
 .../main/org/apache/sis/storage/FeatureQuery.java  |   8 +-
 .../org/apache/sis/storage/StorageConnector.java   |   4 +-
 .../apache/sis/storage/event/StoreListeners.java   |   7 +-
 .../main/org/apache/sis/storage/folder/Store.java  |   2 +-
 .../src/org.apache.sis.util/main/module-info.java  |   1 +
 .../main/org/apache/sis/io/LineAppender.java       |   3 +-
 .../main/org/apache/sis/io/TableAppender.java      |   3 +-
 .../main/org/apache/sis/math/MathFunctions.java    |   5 +-
 .../main/org/apache/sis/math/RepeatedVector.java   |   5 +-
 .../main/org/apache/sis/math/SequenceVector.java   |   8 +-
 .../main/org/apache/sis/math/Vector.java           |   9 +-
 .../sis/measure/FormattedCharacterIterator.java    |   7 +-
 .../main/org/apache/sis/measure/UnitDimension.java |   1 -
 .../main/org/apache/sis/measure/UnitFormat.java    |   2 +-
 .../main/org/apache/sis/pending/jdk/JDK19.java     |  22 +++++
 .../org/apache/sis/system/OptionalDependency.java  |   1 -
 .../main/org/apache/sis/util/ArgumentChecks.java   |  19 ++--
 .../main/org/apache/sis/util/CharSequences.java    |   7 +-
 .../main/org/apache/sis/util/Classes.java          |   4 +-
 .../org/apache/sis/util/ConditionallySafe.java}    |  14 +--
 .../main/org/apache/sis/util/Locales.java          |   8 +-
 .../main/org/apache/sis/util/Numbers.java          |   2 -
 .../org/apache/sis/util/collection/Containers.java |  30 +++---
 .../sis/util/collection/DefaultTreeTable.java      |   9 +-
 .../apache/sis/util/collection/IntegerList.java    |   8 +-
 .../apache/sis/util/collection/TreeNodeList.java   |  21 ++--
 .../apache/sis/util/collection/WeakHashSet.java    |  43 ++++++---
 .../apache/sis/util/internal/CollectionsExt.java   |   6 +-
 .../sis/util/internal/UnmodifiableArrayList.java   |  23 +++--
 .../main/org/apache/sis/util/internal/Unsafe.java  | 106 +++++++++++++++++++++
 .../main/org/apache/sis/util/internal/X364.java    |   2 -
 .../test/org/apache/sis/test/TestRunner.java       |   4 +-
 .../apache/sis/map/service/GraphicsPortrayer.java  |   4 +-
 .../apache/sis/gui/controls/SyncWindowList.java    |   2 +-
 .../apache/sis/gui/controls/ValueColorMapper.java  |   1 +
 .../apache/sis/gui/coverage/CoverageCanvas.java    |   1 +
 .../apache/sis/gui/coverage/CoverageControls.java  |   6 +-
 .../apache/sis/gui/coverage/CoverageExplorer.java  |   2 +
 .../apache/sis/gui/coverage/CoverageStyling.java   |   1 -
 .../org/apache/sis/gui/coverage/GridViewSkin.java  |   1 -
 .../apache/sis/gui/coverage/IsolineRenderer.java   |   1 -
 .../org/apache/sis/gui/internal/PropertyView.java  |   1 -
 .../main/org/apache/sis/gui/map/MapCanvas.java     |  14 ++-
 .../main/org/apache/sis/gui/map/MapCanvasAWT.java  |   1 +
 .../org/apache/sis/gui/metadata/MetadataTree.java  |   4 +-
 .../sis/gui/metadata/StandardMetadataTree.java     |   1 -
 .../org/apache/sis/gui/referencing/WKTPane.java    |   1 -
 113 files changed, 465 insertions(+), 370 deletions(-)
 copy endorsed/src/org.apache.sis.util/{test/org/apache/sis/test/Performance.java => main/org/apache/sis/util/ConditionallySafe.java} (70%)
 create mode 100644 endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Unsafe.java


(sis) 01/03: Partial cleanup of compiler warnings: - Resolve "unchecked" warnings with an internal `Unsafe` class. - "ThisEscapedInObjectConstruction" replaced by "this-escape". - Remove a few @SuppressWarnings("null") which were too broad.

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit f75d3fb406f8aebeddaa35624c5813ededd48e5e
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Feb 6 15:50:11 2024 +0100

    Partial cleanup of compiler warnings:
    - Resolve "unchecked" warnings with an internal `Unsafe` class.
    - "ThisEscapedInObjectConstruction" replaced by "this-escape".
    - Remove a few @SuppressWarnings("null") which were too broad.
---
 .../sis/buildtools/coding/ReorganizeImports.java   |   5 +-
 .../main/org/apache/sis/console/SIS.java           |   2 +-
 .../apache/sis/feature/DefaultAttributeType.java   |   2 +-
 .../org/apache/sis/feature/DefaultFeatureType.java |   2 +-
 .../main/org/apache/sis/image/ComputedTiles.java   |   1 -
 .../org/apache/sis/index/tree/NodeIterator.java    |   1 -
 .../sis/image/processing/isoline/StepsViewer.java  |   1 -
 .../org/apache/sis/metadata/PropertyAccessor.java  |  23 +++--
 .../main/org/apache/sis/metadata/TreeNode.java     |   8 +-
 .../org/apache/sis/metadata/internal/Merger.java   |  15 +--
 .../main/org/apache/sis/xml/bind/Context.java      |   1 -
 .../apache/sis/xml/bind/lan/LocaleAndCharset.java  |   9 +-
 .../apache/sis/metadata/iso/MarshallingTest.java   |   1 -
 .../sis/profile/japan/netcdf/FactoryForUCAR.java   |   2 +
 .../referencing/gazetteer/FinalLocationType.java   |   6 +-
 .../sis/referencing/gazetteer/LocationFormat.java  |   2 +-
 .../gazetteer/ReferencingByIdentifiers.java        |   2 +-
 .../apache/sis/geometry/WraparoundInEnvelope.java  |   1 -
 .../operation/transform/ConcatenatedTransform.java |   2 +
 .../org/apache/sis/storage/geotiff/DataSubset.java |   1 +
 .../sis/storage/geotiff/ImageFileDirectory.java    |  12 +--
 .../sis/storage/geotiff/writer/TileMatrix.java     |   1 -
 .../sis/storage/netcdf/ucar/DecoderWrapper.java    |   4 +-
 .../apache/sis/storage/sql/SQLStoreProvider.java   |   7 +-
 .../sis/storage/sql/feature/FeatureIterator.java   |   1 +
 .../sis/storage/xml/stream/StaxStreamReader.java   |   3 +-
 .../sis/storage/xml/stream/StaxStreamWriter.java   |   1 -
 .../org/apache/sis/storage/StorageConnector.java   |   4 +-
 .../main/org/apache/sis/storage/folder/Store.java  |   2 +-
 .../sis/measure/FormattedCharacterIterator.java    |   7 +-
 .../main/org/apache/sis/measure/UnitDimension.java |   1 -
 .../main/org/apache/sis/measure/UnitFormat.java    |   2 +-
 .../org/apache/sis/system/OptionalDependency.java  |   1 -
 .../org/apache/sis/util/ConditionallySafe.java     |  38 ++++++++
 .../main/org/apache/sis/util/Numbers.java          |   2 -
 .../apache/sis/util/collection/WeakHashSet.java    |  43 ++++++---
 .../sis/util/internal/UnmodifiableArrayList.java   |  17 +++-
 .../main/org/apache/sis/util/internal/Unsafe.java  | 106 +++++++++++++++++++++
 .../main/org/apache/sis/util/internal/X364.java    |   2 -
 .../apache/sis/gui/controls/SyncWindowList.java    |   2 +-
 .../apache/sis/gui/controls/ValueColorMapper.java  |   1 +
 .../apache/sis/gui/coverage/CoverageCanvas.java    |   1 +
 .../apache/sis/gui/coverage/CoverageControls.java  |   6 +-
 .../apache/sis/gui/coverage/CoverageExplorer.java  |   2 +
 .../apache/sis/gui/coverage/CoverageStyling.java   |   1 -
 .../org/apache/sis/gui/coverage/GridViewSkin.java  |   1 -
 .../apache/sis/gui/coverage/IsolineRenderer.java   |   1 -
 .../org/apache/sis/gui/internal/PropertyView.java  |   1 -
 .../main/org/apache/sis/gui/map/MapCanvas.java     |  14 ++-
 .../main/org/apache/sis/gui/map/MapCanvasAWT.java  |   1 +
 .../org/apache/sis/gui/metadata/MetadataTree.java  |   4 +-
 .../sis/gui/metadata/StandardMetadataTree.java     |   1 -
 .../org/apache/sis/gui/referencing/WKTPane.java    |   1 -
 53 files changed, 278 insertions(+), 100 deletions(-)

diff --git a/buildSrc/src/main/java/org/apache/sis/buildtools/coding/ReorganizeImports.java b/buildSrc/src/main/java/org/apache/sis/buildtools/coding/ReorganizeImports.java
index 6475b372ff..d532b752e1 100644
--- a/buildSrc/src/main/java/org/apache/sis/buildtools/coding/ReorganizeImports.java
+++ b/buildSrc/src/main/java/org/apache/sis/buildtools/coding/ReorganizeImports.java
@@ -197,7 +197,6 @@ public final class ReorganizeImports extends SimpleFileVisitor<Path> {
      * @param  upstream  the branch which is merged in this branch.
      * @throws IOException if an error occurred while reading a file.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private ReorganizeImports(final Path root, final ReorganizeImports upstream) throws IOException {
         this.root = root;
         if (upstream == null) {
@@ -619,11 +618,11 @@ public final class ReorganizeImports extends SimpleFileVisitor<Path> {
      * @throws IOException if an error occurred while writing a file.
      */
     private void rewrite(final String[] branchNames) throws IOException {
-        final Integer bitmask = (1 << branchNames.length) - 1;
+        final Integer allBranches = (1 << branchNames.length) - 1;
         final var lines = new ArrayList<String>();
         for (final Map.Entry<Path,Source> entry : sources.entrySet()) {
             final Path relative = entry.getKey();
-            entry.getValue().writeTo(lines, branchNames, branchesOfFiles.getOrDefault(relative, bitmask));
+            entry.getValue().writeTo(lines, branchNames, branchesOfFiles.getOrDefault(relative, allBranches));
             lines.replaceAll(ReorganizeImports::removeExtraneousSpaces);
             Files.write(root.resolve(relative), lines, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
             lines.clear();
diff --git a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
index 4e01778691..d9d333fb90 100644
--- a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
+++ b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/SIS.java
@@ -86,7 +86,7 @@ public final class SIS extends Static {
          * @param  value  value for the specified option.
          * @return the builder on which to perform chained method calls.
          */
-        @SuppressWarnings({"unchecked", "null"})
+        @SuppressWarnings("unchecked")
         final C set(final Option key, Object value) {
             if (key.hasValue && (value = trim(value)) == null) {
                 final String option = key.label();
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultAttributeType.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultAttributeType.java
index 3aebef67ff..619ed2cdb9 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultAttributeType.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultAttributeType.java
@@ -183,7 +183,7 @@ public class DefaultAttributeType<V> extends FieldType implements AttributeType<
      *
      * @see org.apache.sis.feature.builder.AttributeTypeBuilder
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")    // Okay because used only in package-private class.
+    @SuppressWarnings("this-escape")        // Okay because used only in package-private class.
     public DefaultAttributeType(final Map<String,?> identification, final Class<V> valueClass,
             final int minimumOccurs, final int maximumOccurs, final V defaultValue,
             final AttributeType<?>... characterizedBy)
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultFeatureType.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultFeatureType.java
index fa49c05e76..dd68969bbb 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultFeatureType.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/DefaultFeatureType.java
@@ -257,7 +257,7 @@ public class DefaultFeatureType extends AbstractIdentifiedType implements Featur
      *
      * @see org.apache.sis.feature.builder.FeatureTypeBuilder
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
+    @SuppressWarnings("this-escape")
     public DefaultFeatureType(final Map<String,?> identification, final boolean isAbstract,
             final FeatureType[] superTypes, final PropertyType... properties)
     {
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
index 3f8405530c..82778d97e1 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
@@ -82,7 +82,6 @@ final class ComputedTiles extends WeakReference<ComputedImage> implements Dispos
      * @param  image  the image for which to release tiles on garbage-collection.
      * @param  ws     sources to observe for changes, or {@code null} if none.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     ComputedTiles(final ComputedImage image, final WritableRenderedImage[] ws) {
         super(image, ReferenceQueueConsumer.QUEUE);
         cachedTiles = new HashMap<>();
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/index/tree/NodeIterator.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/index/tree/NodeIterator.java
index a190d1ccde..32b17fdc50 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/index/tree/NodeIterator.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/index/tree/NodeIterator.java
@@ -94,7 +94,6 @@ class NodeIterator<E> implements Spliterator<E>, Cloneable {
      * Creates a new iterator for the specified search region.
      * If the given region is null, then infinite bounds are assumed.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     NodeIterator(final PointTree<E> tree, final Envelope searchRegion) {
         final int n = tree.getDimension();
         bitmask = Numerics.bitmask(1 << n) - 1;
diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/processing/isoline/StepsViewer.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/processing/isoline/StepsViewer.java
index a47d255ecd..a81b277f74 100644
--- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/processing/isoline/StepsViewer.java
+++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/processing/isoline/StepsViewer.java
@@ -154,7 +154,6 @@ public final class StepsViewer extends JComponent implements BiConsumer<String,I
      * @param  data  the source of data for isolines.
      * @param  pane  the container where to add components.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private StepsViewer(final RenderedImage data, final Container pane) {
         isolines    = new EnumMap<>(PolylineStage.class);
         stageColors = new Color[] {Color.YELLOW, Color.PINK, Color.BLUE};
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java
index 5fd1314881..ebff2363fe 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java
@@ -41,11 +41,12 @@ import org.apache.sis.util.ObjectConverters;
 import org.apache.sis.util.UnconvertibleObjectException;
 import org.apache.sis.util.internal.CollectionsExt;
 import org.apache.sis.util.internal.Numerics;
-import org.apache.sis.measure.ValueRange;
+import org.apache.sis.util.internal.Unsafe;
 import org.apache.sis.util.collection.CheckedContainer;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.xml.IdentifiedObject;
+import org.apache.sis.measure.ValueRange;
 import static org.apache.sis.metadata.PropertyComparator.*;
 import static org.apache.sis.metadata.ValueExistencePolicy.isNullOrEmpty;
 import static org.apache.sis.util.internal.CollectionsExt.snapshot;
@@ -232,6 +233,7 @@ class PropertyAccessor {
      * @param  standardImpl    the implementation specified by the {@link MetadataStandard}, or {@code null} if none.
      *                         This is the same as {@code implementation} unless a custom implementation is used.
      */
+    @SuppressWarnings("LocalVariableHidesMemberVariable")
     PropertyAccessor(final Class<?> type, final Class<?> implementation, final Class<?> standardImpl) {
         assert type.isAssignableFrom(implementation) : implementation;
         this.type           = type;
@@ -499,6 +501,7 @@ class PropertyAccessor {
      * @return the index of the given name, or -1 if none and {@code mandatory} is {@code false}.
      * @throws IllegalArgumentException if the name is not found and {@code mandatory} is {@code true}.
      */
+    @SuppressWarnings("StringEquality")
     final int indexOf(final String name, final boolean mandatory) {
         Integer index = mapping.get(name);
         if (index == null) {
@@ -508,7 +511,7 @@ class PropertyAccessor {
              * directly the given String instance allow usage of its cached hash code value.
              */
             final String key = CharSequences.replace(name, " ", "").toString().toLowerCase(Locale.ROOT).strip();
-            if (key == name || (index = mapping.get(key)) == null) { // Identity comparison is okay here.
+            if (key == name || (index = mapping.get(key)) == null) {        // Identity comparison is okay here.
                 if (!mandatory) {
                     return -1;
                 }
@@ -622,8 +625,8 @@ class PropertyAccessor {
      */
     final boolean isCollectionOrMap(final int index) {
         if (index >= 0 && index < allCount) {
-            final Class<?> type = getters[index].getReturnType();
-            return Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type);
+            final Class<?> pt = getters[index].getReturnType();
+            return Collection.class.isAssignableFrom(pt) || Map.class.isAssignableFrom(pt);
         }
         return false;
     }
@@ -657,6 +660,7 @@ class PropertyAccessor {
      */
     @SuppressWarnings({"unchecked","rawtypes"})
     final synchronized ExtendedElementInformation information(final Citation standard, final int index) {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         ExtendedElementInformation[] informations = this.informations;
         if (informations == null) {
             this.informations = informations = new PropertyInformation<?>[standardCount];
@@ -1065,8 +1069,7 @@ class PropertyAccessor {
                  * runtime. However, other implementations could use unchecked collection.
                  * There is not much we can do...
                  */
-                // No @SuppressWarnings because this is a real hole.
-                changed = ((Collection) addTo).addAll(elementList);
+                changed = Unsafe.addAll(addTo, elementList);
             }
         }
         /*
@@ -1090,14 +1093,14 @@ class PropertyAccessor {
     @SuppressWarnings({"unchecked","rawtypes"})
     private void convert(final Object[] elements, final Class<?> targetType) throws ClassCastException {
         boolean hasNewConverter = false;
-        ObjectConverter<?,?> converter = null;
+        ObjectConverter converter = null;               // Intentionally raw type. Checks are done below.
         for (int i=0; i<elements.length; i++) {
             final Object value = elements[i];
             if (value != null) {
                 final Class<?> sourceType = value.getClass();
                 if (!targetType.isAssignableFrom(sourceType)) try {
                     if (converter == null) {
-                        converter = lastConverter;              // Volatile field - read only if needed.
+                        converter = lastConverter;      // Volatile field - read only if needed.
                     }
                     /*
                      * Require the exact same classes, not parent or subclass,
@@ -1109,7 +1112,7 @@ class PropertyAccessor {
                         converter = ObjectConverters.find(sourceType, targetType);
                         hasNewConverter = true;
                     }
-                    elements[i] = ((ObjectConverter) converter).apply(value);
+                    elements[i] = converter.apply(value);
                 } catch (UnconvertibleObjectException cause) {
                     throw (ClassCastException) new ClassCastException(Errors.format(
                             Errors.Keys.IllegalClass_2, targetType, sourceType)).initCause(cause);
@@ -1117,7 +1120,7 @@ class PropertyAccessor {
             }
         }
         if (hasNewConverter) {
-            lastConverter = converter;                          // Volatile field - store only if needed.
+            lastConverter = converter;          // Volatile field - store only if needed.
         }
     }
 
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeNode.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeNode.java
index 66625ac9cb..54e6450b54 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeNode.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/TreeNode.java
@@ -34,6 +34,7 @@ import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverters;
 import org.apache.sis.util.internal.CollectionsExt;
+import org.apache.sis.util.internal.Unsafe;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.collection.TreeTable.Node;
@@ -735,8 +736,7 @@ class TreeNode implements Node {
                  * runtime. However, other implementations could use unchecked collection. We have
                  * done our best for converting the type above, there is not much more we can do...
                  */
-                // No @SuppressWarnings because this is a real hole.
-                ((List) values).set(indexInList, value);
+                Unsafe.set((List<?>) values, indexInList, value);
             } catch (IndexOutOfBoundsException e) {
                 // Same rational as in the getUserObject() method.
                 throw new ConcurrentModificationException(e);
@@ -973,6 +973,7 @@ class TreeNode implements Node {
      */
     private TreeNodeChildren getCompactChildren() {
         if (table.valuePolicy == ValueExistencePolicy.COMPACT) {
+            @SuppressWarnings("LocalVariableHidesMemberVariable")
             final Collection<Node> children = getChildren();
             if (children instanceof TreeNodeChildren) {
                 return (TreeNodeChildren) children;
@@ -1000,6 +1001,7 @@ class TreeNode implements Node {
             }
             value = name;
         } else if (column == TableColumn.TYPE) {
+            @SuppressWarnings("LocalVariableHidesMemberVariable")
             final TreeNodeChildren children = getCompactChildren();
             if (children == null || (value = children.getParentType()) == null) {
                 value = baseType;
@@ -1008,6 +1010,7 @@ class TreeNode implements Node {
             if (isLeaf()) {
                 value = getNonNilValue();
             } else {
+                @SuppressWarnings("LocalVariableHidesMemberVariable")
                 final TreeNodeChildren children = getCompactChildren();
                 if (children != null) {
                     value = children.getParentTitle();
@@ -1037,6 +1040,7 @@ class TreeNode implements Node {
         ArgumentChecks.ensureNonNull("column", column);
         if (column == TableColumn.VALUE) {
             ArgumentChecks.ensureNonNull("value", value);                       // See javadoc.
+            @SuppressWarnings("LocalVariableHidesMemberVariable")
             final TreeNodeChildren children = getCompactChildren();
             if (children == null || !(children.setParentTitle(value))) {
                 setUserObject(value);
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Merger.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Merger.java
index dc4f5091f8..811da3f7b0 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Merger.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/Merger.java
@@ -31,6 +31,7 @@ import org.apache.sis.metadata.KeyNamePolicy;
 import org.apache.sis.metadata.ValueExistencePolicy;
 import org.apache.sis.util.CorruptedObjectException;
 import org.apache.sis.util.Classes;
+import org.apache.sis.util.internal.Unsafe;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -181,7 +182,8 @@ public class Merger {
                                                : targetMap.putIfAbsent(propertyName, sourceValue);
             if (targetValue != null) {
                 if (targetValue instanceof ModifiableMetadata) {
-                    success = copy(sourceValue, (ModifiableMetadata) targetValue, dryRun);
+                    final var md = (ModifiableMetadata) targetValue;
+                    success = copy(sourceValue, md, dryRun);
                     if (!success) {
                         /*
                          * This exception may happen if the source is a subclass of the target. This is the converse
@@ -192,8 +194,7 @@ public class Merger {
                          */
                         if (dryRun) break;
                         throw new InvalidMetadataException(errors().getString(Errors.Keys.IllegalPropertyValueClass_3,
-                                name(target, propertyName), ((ModifiableMetadata) targetValue).getInterface(),
-                                Classes.getClass(sourceValue)));
+                                    name(target, propertyName), md.getInterface(), Classes.getClass(sourceValue)));
                     }
                 } else if (targetValue instanceof Collection<?>) {
                     /*
@@ -315,11 +316,11 @@ distribute:                 while (it.hasNext()) {
                     }
                 } else {
                     /*
-                     * No @SuppressWarnings("unchecked") because this is really unchecked. However, since the two maps
-                     * have been fetched by calls to the same getter method on two org.apache.sis.metadata.iso objects,
-                     * the types should.
+                     * The two maps have been fetched by calls to the same getter method on the two metadata objects,
+                     * so they should have the same types declared by the method signature. However we cannot be sure
+                     * that the user didn't override the method with specialized types.
                      */
-                    ((Map) target).merge(pe.getKey(), newValue, this);
+                    Unsafe.merge(target, pe.getKey(), newValue, this);
                 }
             }
             return true;
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java
index ac612f701f..d7208fc157 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/Context.java
@@ -284,7 +284,6 @@ public final class Context extends MarshalContext {
      * @param  converter        the converter in use.
      * @param  logFilter        the object to inform about warnings.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public Context(int                       bitMasks,
                    final MarshallerPool      pool,
                    final Locale              locale,
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java
index 6a48a60757..5cbea92b82 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java
@@ -27,6 +27,7 @@ import java.util.Iterator;
 import java.nio.charset.Charset;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.internal.Bag;
+import org.apache.sis.util.internal.Unsafe;
 import org.apache.sis.util.internal.CollectionsExt;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.collection.TreeTable.Node;
@@ -225,11 +226,11 @@ public final class LocaleAndCharset implements Node {
         @Override public <V> void setValue(final TableColumn<V> column, V value) {
             if (TableColumn.VALUE.equals(column)) {
                 /*
-                 * No @SuppressWarning("unchecked") because following is a real hole.
-                 * We rely on Entry.setValue(Object) implementation to perform checks
-                 * (this is the case with SIS implementation backed by PropertyAccessor).
+                 * We rely on Entry.setValue(Object) implementation to perform type checks.
+                 * This is the case with SIS implementation backed by PropertyAccessor,
+                 * but we cannot guarantee that this is the case with user-provided map.
                  */
-                ((Map.Entry<?,V>) node.getUserObject()).setValue(value);
+                Unsafe.setValue((Map.Entry<?,?>) node.getUserObject(), value);
             } else {
                 node.setValue(column, value);
             }
diff --git a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/MarshallingTest.java b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/MarshallingTest.java
index 104794c77f..03db6339a1 100644
--- a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/MarshallingTest.java
+++ b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/MarshallingTest.java
@@ -105,7 +105,6 @@ public final class MarshallingTest extends TestUsingFile implements Filter {
      *
      * @throws JAXBException if an error occurred while preparing the marshaller.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public MarshallingTest() throws JAXBException {
         output     = new StringWriter();
         pool       = getMarshallerPool();
diff --git a/endorsed/src/org.apache.sis.profile.japan/main/org/apache/sis/profile/japan/netcdf/FactoryForUCAR.java b/endorsed/src/org.apache.sis.profile.japan/main/org/apache/sis/profile/japan/netcdf/FactoryForUCAR.java
index e137255210..5a6b01eeda 100644
--- a/endorsed/src/org.apache.sis.profile.japan/main/org/apache/sis/profile/japan/netcdf/FactoryForUCAR.java
+++ b/endorsed/src/org.apache.sis.profile.japan/main/org/apache/sis/profile/japan/netcdf/FactoryForUCAR.java
@@ -74,6 +74,7 @@ public final class FactoryForUCAR implements CoordSystemBuilderFactory {
      * @return the coordinate system builder for the given dataset.
      */
     @Override
+    @SuppressWarnings("rawtypes")
     public CoordSystemBuilder open(NetcdfDataset.Builder dsb) {         // TODO: add <?> with UCAR netCDF 6.
         return new CSBuilder(dsb);
     }
@@ -107,6 +108,7 @@ public final class FactoryForUCAR implements CoordSystemBuilderFactory {
          * Only called for variables already identified as Coordinate Axes.
          */
         @Override
+        @SuppressWarnings("rawtypes")
         protected AxisType getAxisType(final VariableDS.Builder variable) {       // TODO: add <?> with UCAR netCDF 6.
             final AxisType type = super.getAxisType(variable);
             if (type == null) {
diff --git a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
index 44e799fcfd..17b9f10eb7 100644
--- a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
+++ b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
@@ -112,7 +112,7 @@ final class FinalLocationType extends AbstractLocationType implements Serializab
      * @param rs        the reference system that comprises this location type.
      * @param existing  other {@code FinalLocationType} instances created before this one.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
+    @SuppressWarnings("LocalVariableHidesMemberVariable")
     private FinalLocationType(final LocationType source, final ReferenceSystemUsingIdentifiers rs,
             final Map<LocationType, FinalLocationType> existing)
     {
@@ -216,7 +216,9 @@ final class FinalLocationType extends AbstractLocationType implements Serializab
     private static <T> T unmodifiable(final Class<T> type, T metadata) {
         if (metadata instanceof ModifiableMetadata) {
             metadata = MetadataCopier.forModifiable(((ModifiableMetadata) metadata).getStandard()).copy(type, metadata);
-            ((ModifiableMetadata) metadata).transitionTo(ModifiableMetadata.State.FINAL);
+            if (metadata instanceof ModifiableMetadata) {
+                ((ModifiableMetadata) metadata).transitionTo(ModifiableMetadata.State.FINAL);
+            }
         }
         return metadata;
     }
diff --git a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
index fd42702ca6..3cccc4f551 100644
--- a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
+++ b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
@@ -201,7 +201,7 @@ public class LocationFormat extends TabularFormat<Location> {
      * @throws IOException if an error occurred while writing to the given appendable.
      */
     @Override
-    @SuppressWarnings({"fallthrough", "null"})
+    @SuppressWarnings("fallthrough")
     public void format(final Location location, final Appendable toAppendTo) throws IOException {
         ArgumentChecks.ensureNonNull("location", location);
         final Locale locale = getLocale(Locale.Category.DISPLAY);
diff --git a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
index 54b83c5af2..ea366663cc 100644
--- a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
+++ b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
@@ -172,7 +172,7 @@ public abstract class ReferencingByIdentifiers extends AbstractReferenceSystem i
      * @param properties  the properties to be given to the reference system.
      * @param types       description of location type(s) in the spatial reference system.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
+    @SuppressWarnings("this-escape")
     public ReferencingByIdentifiers(final Map<String,?> properties, final LocationType... types) {
         super(properties);
         theme = Types.toInternationalString(properties, THEME_KEY);
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundInEnvelope.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundInEnvelope.java
index 5e7dc58e1f..bfff4b5f29 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundInEnvelope.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/WraparoundInEnvelope.java
@@ -180,7 +180,6 @@ final class WraparoundInEnvelope extends WraparoundTransform {
          * Creates a new instance using the given transform. If the given transform contains wraparound steps,
          * then the transform stored in the {@link #transform} will be a different transform chains instance.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         Controller(final MathTransform transform) {
             this.transform = replace(transform, this);
         }
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
index a867caf80a..7fe7306481 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
@@ -209,6 +209,7 @@ class ConcatenatedTransform extends AbstractMathTransform implements Serializabl
         boolean inverseCaseTested = false;
         if (tr1 instanceof AbstractMathTransform) {
             // TODO: after removal of the deprecated method, invoke `tryConcatenate(Joiner)` only once.
+            @SuppressWarnings("removal")
             final MathTransform optimized = ((AbstractMathTransform) tr1).tryConcatenate(false, tr2, factory);
             inverseCaseTested = true;
             if (optimized != null) {
@@ -217,6 +218,7 @@ class ConcatenatedTransform extends AbstractMathTransform implements Serializabl
             }
         }
         if (tr2 instanceof AbstractMathTransform) {
+            @SuppressWarnings("removal")
             final MathTransform optimized = ((AbstractMathTransform) tr2).tryConcatenate(true, tr1, factory);
             inverseCaseTested = true;
             if (optimized != null) {
diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
index 5533d9d3af..401c0eb3f4 100644
--- a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
+++ b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
@@ -323,6 +323,7 @@ class DataSubset extends TiledGridCoverage implements Localized {
      *         (too many exception types to list them all).
      */
     @Override
+    @SuppressWarnings("try")
     protected final Raster[] readTiles(final AOI iterator) throws IOException, DataStoreException {
         /*
          * Prepare an array for all tiles to be returned. Tiles that are already in memory will be stored
diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index 00b0b9b3e8..67ce259321 100644
--- a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++ b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -960,13 +960,10 @@ final class ImageFileDirectory extends DataCube {
              */
             case TAG_PAGE_NUMBER: {
                 final Vector v = type.readAsVector(input(), count);
-                int p = 0, n = 0;
-                switch (v.size()) {
-                    default: n = v.intValue(1);     // Fall through
-                    case 1:  p = v.intValue(0);
-                    case 0:  break;
+                final int n = v.size();
+                if (n >= 1) {
+                    metadata.addPage(v.intValue(0), (n >= 2) ? v.intValue(1) : 0);
                 }
-                metadata.addPage(p, n);
                 break;
             }
             /*
@@ -1369,6 +1366,7 @@ final class ImageFileDirectory extends DataCube {
      */
     @Override
     protected Metadata createMetadata() throws DataStoreException {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final ImageMetadataBuilder metadata = this.metadata;
         if (metadata == null) {
             /*
@@ -1390,6 +1388,7 @@ final class ImageFileDirectory extends DataCube {
          */
         final boolean isIndexValid = !isReducedResolution();
         metadata.newCoverage(isIndexValid && reader.store.customizer.isElectromagneticMeasurement(index));
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final List<SampleDimension> sampleDimensions = getSampleDimensions();
         for (int band = 0; band < samplesPerPixel; band++) {
             metadata.addNewBand(sampleDimensions.get(band));
@@ -1406,6 +1405,7 @@ final class ImageFileDirectory extends DataCube {
          * Destination: metadata/spatialRepresentationInfo and others.
          */
         if (referencing != null) {
+            @SuppressWarnings("LocalVariableHidesMemberVariable")
             final GridGeometry gridGeometry = getGridGeometry();
             if (gridGeometry.isDefined(GridGeometry.ENVELOPE)) {
                 metadata.addExtent(gridGeometry.getEnvelope(), listeners);
diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
index 48d2f83dc6..15c332f334 100644
--- a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
+++ b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
@@ -190,7 +190,6 @@ public final class TileMatrix {
      * @throws DataStoreException if the compression method is unsupported.
      * @throws IOException if an error occurred while writing to the given output.
      */
-    @SuppressWarnings("null")
     public void writeRasters(final ChannelDataOutput output) throws DataStoreException, IOException {
         ChannelDataOutput compOutput  = null;
         PixelChannel      compressor  = null;
diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
index c72c220c55..d64e8e6023 100644
--- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
+++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
@@ -132,7 +132,6 @@ public final class DecoderWrapper extends Decoder implements CancelTask {
      * @param  listeners  where to send the warnings.
      * @throws IOException if an error occurred while opening the netCDF file.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public DecoderWrapper(final String filename, final GeometryLibrary geomlib, final StoreListeners listeners)
             throws IOException
     {
@@ -394,7 +393,7 @@ public final class DecoderWrapper extends Decoder implements CancelTask {
      * @return all variables, or an empty array if none.
      */
     @Override
-    @SuppressWarnings({"ReturnOfCollectionOrArrayField", "null"})
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     public Variable[] getVariables() {
         if (variables == null) {
             final List<? extends ucar.nc2.Variable> all = file.getVariables();
@@ -448,6 +447,7 @@ public final class DecoderWrapper extends Decoder implements CancelTask {
      */
     @Override
     public DiscreteSampling[] getDiscreteSampling(final DataStore lock) throws IOException, DataStoreException {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final FeatureDataset features = getFeatureDataSet();
         if (features instanceof FeatureDatasetPoint) {
             final List<DsgFeatureCollection> fc = ((FeatureDatasetPoint) features).getPointFeatureCollectionList();
diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStoreProvider.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStoreProvider.java
index d817f24b67..13c1187536 100644
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStoreProvider.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStoreProvider.java
@@ -106,13 +106,15 @@ public class SQLStoreProvider extends DataStoreProvider {
      *
      * @since 1.1
      */
-    public static final ParameterDescriptor<Map> QUERIES_PARAM;
+    public static final ParameterDescriptor<Map<?,?>> QUERIES_PARAM;
 
     /**
      * The parameter descriptor to be returned by {@link #getOpenParameters()}.
      */
     private static final ParameterDescriptorGroup OPEN_DESCRIPTOR;
     static {
+        @SuppressWarnings("unchecked")
+        final Class<Map<?,?>> map = (Class) Map.class;
         final ParameterBuilder builder = new ParameterBuilder();
         SOURCE_PARAM = builder.addName(LOCATION).setRequired(true)
                               .setDescription(Resources.formatInternational(Resources.Keys.DataSource))
@@ -122,7 +124,7 @@ public class SQLStoreProvider extends DataStoreProvider {
                               .create(GenericName[].class, null);
         QUERIES_PARAM = builder.addName(QUERIES)
                               .setDescription(Resources.formatInternational(Resources.Keys.MappedSQLQueries))
-                              .create(Map.class, null);
+                              .create(map, null);
         OPEN_DESCRIPTOR = builder.addName(NAME).createGroup(SOURCE_PARAM, TABLES_PARAM, QUERIES_PARAM);
     }
 
@@ -184,6 +186,7 @@ public class SQLStoreProvider extends DataStoreProvider {
      * @throws DataStoreException if an SQL error occurred.
      */
     @Override
+    @SuppressWarnings("try")
     public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException {
         final DataSource ds = connector.getStorageAs(DataSource.class);
         if (ds != null) {
diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
index 83be457a0c..fee6ee9013 100644
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
@@ -322,6 +322,7 @@ final class FeatureIterator implements Spliterator<Feature>, AutoCloseable {
      * Closes the (pooled) connection, including the statements of all dependencies.
      */
     @Override
+    @SuppressWarnings("try")
     public void close() throws SQLException {
         if (spatialInformation != null) {
             spatialInformation.close();
diff --git a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
index ed5157fbdd..0d802ce569 100644
--- a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
+++ b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
@@ -133,10 +133,9 @@ public abstract class StaxStreamReader extends StaxStreamIO implements XMLStream
      * @throws IOException if an error occurred while preparing the input stream.
      * @throws Exception if another kind of error occurred while closing a previous stream.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     protected StaxStreamReader(final StaxDataStore owner) throws Exception {
         super(owner);
-        reader = owner.createReader(this);      // Okay because will not store the 'this' reference.
+        reader = owner.createReader(this);      // Okay because will not store the `this` reference.
     }
 
     /**
diff --git a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamWriter.java b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamWriter.java
index d566a73c34..8b1f55a76e 100644
--- a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamWriter.java
+++ b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamWriter.java
@@ -110,7 +110,6 @@ public abstract class StaxStreamWriter extends StaxStreamIO implements Consumer<
      * @throws XMLStreamException if an error occurred while opening the XML file.
      * @throws IOException if an error occurred while preparing the output stream.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     protected StaxStreamWriter(final StaxDataStore owner, final OutputStream temporary)
             throws DataStoreException, XMLStreamException, IOException
     {
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java
index 59869cd3ac..8eba8409cc 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/StorageConnector.java
@@ -1110,6 +1110,7 @@ public class StorageConnector implements Serializable {
          * ChannelDataInput depends on ReadableByteChannel, which itself depends on storage
          * (potentially an InputStream). We need to remember this chain in `Coupled` objects.
          */
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final String name = getStorageName();
         final ReadableByteChannel channel = factory.readable(name, null);
         addView(ReadableByteChannel.class, channel, null, factory.isCoupled() ? CASCADE_ON_RESET : 0);
@@ -1194,7 +1195,7 @@ public class StorageConnector implements Serializable {
      * @return the byte buffer to use with {@link ChannelDataInput} or {@link ChannelDataOutput}.
      */
     private ByteBuffer getChannelBuffer(final ChannelFactory factory) {
-        @SuppressWarnings("deprecated")
+        @SuppressWarnings("deprecation")
         ByteBuffer buffer = getOption(OptionKey.BYTE_BUFFER);               // User-supplied buffer.
         if (buffer == null) {
             if (factory.suggestDirectBuffer) {
@@ -1495,6 +1496,7 @@ public class StorageConnector implements Serializable {
          * ChannelDataOutput depends on WritableByteChannel, which itself depends on storage
          * (potentially an OutputStream). We need to remember this chain in `Coupled` objects.
          */
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final String name = getStorageName();
         final WritableByteChannel channel = factory.writable(name, null);
         addView(WritableByteChannel.class, channel, null, factory.isCoupled() ? CASCADE_ON_RESET : 0);
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java
index f6821a7fd4..ac901eb4b7 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/Store.java
@@ -160,7 +160,6 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D
      * @throws DataStoreException if an error occurred while fetching the directory {@link Path}.
      * @throws IOException if an error occurred while using the directory {@code Path}.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")    // Okay because 'children' does not escape.
     Store(final DataStoreProvider provider, final StorageConnector connector, final Path path, final DataStoreProvider format)
             throws DataStoreException, IOException
     {
@@ -265,6 +264,7 @@ class Store extends DataStore implements StoreResource, UnstructuredAggregate, D
                            configuration.getOption(OptionKey.ENCODING),
                            MetadataBuilder.Scope.RESOURCE);
 
+            @SuppressWarnings("LocalVariableHidesMemberVariable")
             final GenericName identifier = identifier(null);
             String name = null;
             if (identifier != null) {
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/FormattedCharacterIterator.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/FormattedCharacterIterator.java
index 07585d548a..9cf58b5762 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/FormattedCharacterIterator.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/FormattedCharacterIterator.java
@@ -93,7 +93,6 @@ final class FormattedCharacterIterator extends SimpleCharacterIterator implement
          * Creates a new entry for the given value, together with the range of index where
          * the field value has been formatted. See class javadoc for more information.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         Entry(final Attribute field, final Object value, final int start, final int limit,
                 final Map<Attribute,Entry> attributes)
         {
@@ -175,9 +174,9 @@ final class FormattedCharacterIterator extends SimpleCharacterIterator implement
                 for (final Map.Entry<Attribute,Object> entry : it.getAttributes().entrySet()) {
                     final Attribute attribute = entry.getKey();
                     if (it.getRunLimit(attribute) == currentRunLimit) {
-                        final Entry e = new Entry(attribute, entry.getValue(),  // Constructeur adds itself to the map.
-                                                  offset + it.getRunStart(attribute),
-                                                  offset + currentRunLimit, attributes);
+                        var e = new Entry(attribute, entry.getValue(),  // Constructeur adds itself to the map.
+                                          offset + it.getRunStart(attribute),
+                                          offset + currentRunLimit, attributes);
                     }
                 }
             }
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitDimension.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitDimension.java
index 46789f77db..b6afc7861d 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitDimension.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitDimension.java
@@ -90,7 +90,6 @@ final class UnitDimension implements Dimension, Serializable {
      *
      * @param  symbol  the symbol of this base dimension (not to be confused with unit symbol).
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")    // Safe because this class is final.
     UnitDimension(final char symbol) {
         this.symbol = symbol;
         components  = Map.of(this, new Fraction(1,1).unique());
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java
index 5b3f7f4414..2ed8106ea8 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java
@@ -1110,7 +1110,7 @@ appPow: if (unit == null) {
      * @throws MeasurementParseException if a problem occurred while parsing the given symbols.
      */
     @Override
-    @SuppressWarnings({"null", "fallthrough"})
+    @SuppressWarnings("fallthrough")
     public Unit<?> parse(CharSequence symbols, final ParsePosition position) throws MeasurementParseException {
         ArgumentChecks.ensureNonNull("symbols",  symbols);
         ArgumentChecks.ensureNonNull("position", position);
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/OptionalDependency.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/OptionalDependency.java
index 78164b292f..d4a532de10 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/OptionalDependency.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/system/OptionalDependency.java
@@ -43,7 +43,6 @@ public abstract class OptionalDependency extends SystemListener {
      * @param module  a constant from the {@link Modules} class which identify the module that need the optional dependency.
      * @param dependency  the name of the optional module on which the specified {@code module} depends.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     protected OptionalDependency(final String module, final String dependency) {
         super(module);
         this.dependency = dependency;
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ConditionallySafe.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ConditionallySafe.java
new file mode 100644
index 0000000000..70fe7d327a
--- /dev/null
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ConditionallySafe.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.util;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Annotates a code with parameterized types that are safe only under some conditions.
+ * The source code of the method typically has a {@code @SuppressWarnings("unchecked")}
+ * annotation despite the fact that the warning is not fully resolved. The Javadoc shall
+ * document the conditions that are necessary for the method to be safe.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD, ElementType.LOCAL_VARIABLE})
+public @interface ConditionallySafe {
+}
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Numbers.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Numbers.java
index eb993129d4..32cddf40ca 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Numbers.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Numbers.java
@@ -109,7 +109,6 @@ public final class Numbers extends Static {
     /**
      * Creates an entry for a type which is not a primitive type.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private Numbers(final Class<?> type, final boolean isFloat, final boolean isInteger, final byte ordinal) {
         primitive = wrapper = type;
         this.isFloat   = isFloat;
@@ -126,7 +125,6 @@ public final class Numbers extends Static {
     /**
      * Creates a mapping between a primitive type and its wrapper.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private Numbers(final Class<?> primitive, final Class<?> wrapper,
                     final boolean  isFloat,   final boolean  isInteger,
                     final byte     size,      final byte     ordinal,
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/WeakHashSet.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/WeakHashSet.java
index 2aa4d8890a..24bb09ba57 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/WeakHashSet.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/WeakHashSet.java
@@ -25,6 +25,7 @@ import org.apache.sis.util.Debug;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ConditionallySafe;
 import static org.apache.sis.util.collection.WeakEntry.*;
 
 
@@ -256,7 +257,7 @@ public class WeakHashSet<E> extends AbstractSet<E> implements CheckedContainer<E
     }
 
     /**
-     * Returns an object equals to {@code element} if such an object already exist in this
+     * Returns an object equals to {@code element} if such an object already exists in this
      * {@code WeakHashSet}. Otherwise, adds {@code element} to this {@code WeakHashSet}.
      * This method is functionally equivalents to the following code:
      *
@@ -272,30 +273,47 @@ public class WeakHashSet<E> extends AbstractSet<E> implements CheckedContainer<E
      *     return element;
      *     }
      *
-     * @param  <T>      the type of the element to get. Can be {@code null}.
-     * @param  element  the element to get or to add in the set if not already presents,
-     *                  or {@code null} if the given element was null.
-     * @return an element equals to the given one if already presents in the set,
-     *         or the given {@code object} otherwise.
+     * <h4>Requirement for type safety</h4>
+     * This method is safe only if the given {@code element} implements the {@link Object#equals(Object)} method
+     * in such a way that {@code T.equals(x)} can be true only if <var>x</var> is an instance of <var>T</var>.
+     * This requirement is true in the common case when the {@code equals(Object)} implementation requires that
+     * the two compared objects are of the same class, for example as below:
+     *
+     * {@snippet lang="java" :
+     *     @Override
+     *     public boolean equals(Object obj) {
+     *         if (obj == null || obj.getClass() != getClass()) {
+     *             return false;
+     *         }
+     *         // Do the comparison
+     *     }
+     *
+     * @param  <T>      the type of the element to get.
+     * @param  element  the element to get or to add in the set if not already presents. Can be {@code null}.
+     * @return an element equals to the given one if already presents in the set, or the given {@code element}
+     *         otherwise. Can be {@code null} if the given element was null.
      */
+    @ConditionallySafe
+    @SuppressWarnings("unchecked")
     public synchronized <T extends E> T unique(final T element) {
         /*
-         * There is no way to make sure that this operation is really safe.
-         * We have to trust the Object.equals(Object) method to be strict
+         * It is difficult to make sure that this operation is really safe.
+         * We have to trust the `Object.equals(Object)` method to be strict
          * about the type of compared objects.
          */
-        return (T) intern(element, INTERN);
+        return (T) intern(element, UNIQUE);
     }
 
     // Arguments for the {@link #intern} method.
     /** The "remove" operation.  */  private static final int REMOVE = -1;
     /** The "get"    operation.  */  private static final int GET    =  0;
     /** The "add"    operation.  */  private static final int ADD    = +1;
-    /** The "intern" operation.  */  private static final int INTERN = +2;
+    /** The "unique" operation.  */  private static final int UNIQUE = +2;
 
     /**
      * Implementation of the {@link #add(Object)}, {@link #remove(Object)}, {@link #get(Object)},
-     * {@link #contains(Object)} and {@link #unique(Object)} methods.
+     * {@link #contains(Object)} and {@link #unique(Object)} methods. Tests for equality are done
+     * on the given object (this is implied by the {@link #unique(Object)} method contract).
      */
     private E intern(final Object obj, final int operation) {
         assert isValid();
@@ -304,6 +322,7 @@ public class WeakHashSet<E> extends AbstractSet<E> implements CheckedContainer<E
              * Check if the object is already contained in this
              * WeakHashSet. If yes, return the existing element.
              */
+            @SuppressWarnings("LocalVariableHidesMemberVariable")
             Entry[] table = this.table;
             final int hash = (mayContainArrays ? Utilities.deepHashCode(obj) : obj.hashCode()) & HASH_MASK;
             int index = hash % table.length;
@@ -332,7 +351,7 @@ public class WeakHashSet<E> extends AbstractSet<E> implements CheckedContainer<E
                 final E element = elementType.cast(obj);
                 table[index] = new Entry(element, table[index], hash);
                 assert isValid();
-                if (operation == INTERN) {
+                if (operation == UNIQUE) {
                     return element;
                 }
             }
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java
index 5a48ecd0a7..095d97c107 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java
@@ -23,6 +23,7 @@ import java.util.Objects;
 import java.util.RandomAccess;
 import java.lang.reflect.Array;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.ConditionallySafe;
 import org.apache.sis.util.collection.CheckedContainer;
 
 
@@ -39,7 +40,7 @@ import org.apache.sis.util.collection.CheckedContainer;
  *     List<?> list = Collections.unmodifiableList(Arrays.asList(array));
  *     }
  *
- * except that this class uses one less level of indirection (which may be significant since
+ * except that this class uses one less level of indirection (which may be significant because
  * unmodifiable lists are extensively used in SIS) and implements the {@link CheckedContainer}
  * interface.
  *
@@ -47,7 +48,7 @@ import org.apache.sis.util.collection.CheckedContainer;
  * The {@link #getElementType()} return type is {@code Class<E>}, but its implementation actually
  * returns {@code Class<? extends E>}. This contract violation is possible because Java arrays are
  * covariant (at the contrary of collections). In order to avoid such contract violation, callers
- * <strong>must</strong> ensure that the type of array elements in exactly {@code E}, not a subtype
+ * <strong>must</strong> ensure that the type of array elements is exactly {@code E}, not a subtype
  * of {@code E}. This class has no way to verify that condition. This class is not in the public API
  * for this reason.
  *
@@ -121,11 +122,11 @@ public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomA
      * specified sub-region of the given array shall not be modified after construction if the
      * returned list is intended to be immutable.
      *
-     * <p>This method does not check the validity of the given index.
+     * <p>This method does not check the validity of the given indices.
      * The check must be done by the caller.</p>
      *
      * <h4>WARNING! Type safety hole</h4>
-     * Callers <strong>must</strong> ensure that the type of array elements in exactly {@code E},
+     * Callers <strong>must</strong> ensure that the type of array elements is exactly {@code E},
      * not a subtype of {@code E}. If the caller is okay with {@code List<? extends E>}, then (s)he
      * should use {@link org.apache.sis.util.collection.Containers#unmodifiableList(Object[])} instead.
      * See class javadoc for more information.
@@ -136,6 +137,7 @@ public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomA
      * @param  upper  high endpoint (exclusive) of the sublist.
      * @return the given array wrapped in an unmodifiable list.
      */
+    @ConditionallySafe
     public static <E> UnmodifiableArrayList<E> wrap(final E[] array, final int lower, final int upper) {
         if (lower == 0 && upper == array.length) {
             return new UnmodifiableArrayList<>(array);
@@ -147,11 +149,16 @@ public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomA
      * Returns the element type of the wrapped array. The default implementation returns
      * <code>array.getClass().{@linkplain Class#getComponentType() getComponentType()}</code>.
      *
+     * <h4>Type safety hole</h4>
+     * The returned value is correct only if the condition documented
+     * in {@link #wrap(Object[], int, int)} has been met.
+     *
      * @return the type of elements in the list.
      */
     @Override
+    @ConditionallySafe
+    @SuppressWarnings("unchecked")
     public Class<E> getElementType() {
-        // No @SuppressWarnings because this cast is really unsafe. See class javadoc.
         return (Class<E>) array.getClass().getComponentType();
     }
 
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Unsafe.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Unsafe.java
new file mode 100644
index 0000000000..0011777e88
--- /dev/null
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/Unsafe.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.util.internal;
+
+import java.util.List;
+import java.util.Collection;
+import java.util.Map;
+import java.util.function.BiFunction;
+import org.apache.sis.util.Static;
+import org.apache.sis.util.ConditionallySafe;
+
+
+/**
+ * A central place where to put unsafe methods. Those method should be invoked only in contexts
+ * where the warning cannot be fully resolved. The use of this class allow maintainers to trace
+ * the Apache SIS codes where potentially unsafe operations still exist despite
+ * {@code @SuppressWarnings("unchecked")} annotation.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+public final class Unsafe extends Static {
+    /**
+     * Do not allow instantiation of this class.
+     */
+    private Unsafe() {
+    }
+
+    /**
+     * Adds all elements from one collection to the other. This method bypasses the compiler type safety checks.
+     * This method should be invoked only when, while not sure, the caller thinks that there is reasonably good
+     * reasons to assume that the element types have been or will be verified. For example, it may be a context
+     * where Apache SIS uses {@linkplain java.util.Collections#checkedCollection checked collection} by default
+     * but cannot guarantee that the users didn't override with a non-checked collection.
+     *
+     * @param  target    the collection where to add elements. Should preferably be a checked collection.
+     * @param  elements  the elements to add.
+     * @return whether {@code target} changed as a result of this operation.
+     */
+    @ConditionallySafe
+    @SuppressWarnings("unchecked")
+    public static boolean addAll(Collection<?> target, Collection<?> elements) {
+        return ((Collection) target).addAll(elements);
+    }
+
+    /**
+     * Sets the element at the given index in the given list. This method bypasses the compiler type safety checks.
+     * This method should be invoked only when the caller has done its best effort for ensuring that the element is
+     * an instance of the required type, or when the target list has good chances to be a checked collection.
+     *
+     * @param  target   the list where to set the element. Should preferably be a checked collection.
+     * @param  index    index of the element to set.
+     * @param  element  the element to set in the list.
+     * @return the previous element at the given index.
+     */
+    @ConditionallySafe
+    @SuppressWarnings("unchecked")
+    public static Object set(List<?> target, int index, Object element) {
+        return ((List) target).set(index, element);
+    }
+
+    /**
+     * Merges the value associated to the given key. This method bypasses the compiler type safety checks.
+     * This method should be invoked only when the caller has done its best effort for ensuring that the
+     * value and the merge function have compatible types.
+     *
+     * @param  target  the map where to merge a value.
+     * @param  key     key of the value to merge.
+     * @param  value   value to merge.
+     * @param  remappingFunction the function to apply for merging the given value with the existing one.
+     * @return the new value associated to the key.
+     */
+    @ConditionallySafe
+    @SuppressWarnings("unchecked")
+    public static Object merge(Map<?,?> target, Object key, Object value, BiFunction<?,?,?> remappingFunction) {
+        return ((Map) target).merge(key, value, remappingFunction);
+    }
+
+    /**
+     * Sets the value of a map entry. This method bypasses the compiler type safety checks.
+     * This method should be invoked only when the caller has done its best effort for ensuring
+     * that the value is an instance of the expected type, or if the map is a checked collection.
+     *
+     * @param  target  the entry where to set a value. Should be an entry from a checked collection.
+     * @param  value   the value to set.
+     * @return the previous value.
+     */
+    @ConditionallySafe
+    @SuppressWarnings("unchecked")
+    public static Object setValue(Map.Entry<?,?> target, Object value) {
+        return ((Map.Entry) target).setValue(value);
+    }
+}
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/X364.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/X364.java
index 1979664d30..5cf42b449b 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/X364.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/X364.java
@@ -119,7 +119,6 @@ public enum X364 {
      * @param code   the X.364 numerical code.
      * @param color  the color name, or {@code null} if none.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private X364(final byte code, final String color) {
         this.code  = code;
         this.color = color;
@@ -132,7 +131,6 @@ public enum X364 {
      *
      * @param foreground  the X.364 code for a foreground color.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     private X364(final X364 foreground) {
         this((byte) (foreground.code + 10), foreground.color);
         this.foreground = foreground;
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/SyncWindowList.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/SyncWindowList.java
index 91fc41a7c1..a0345f3911 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/SyncWindowList.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/SyncWindowList.java
@@ -134,7 +134,7 @@ public final class SyncWindowList extends TabularWidget implements ListChangeLis
      * @param  vocabulary  localized resources, given because already known by the caller
      *                     (those arguments would be removed if this constructor was public API).
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
+    @SuppressWarnings("unchecked")
     public SyncWindowList(final WindowHandler owner, final Resources resources, final Vocabulary vocabulary) {
         this.owner = owner;
         table = newTable();
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
index 7b1a8852a3..ef0d02f4a6 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
@@ -346,6 +346,7 @@ public final class ValueColorMapper extends TabularWidget {
      * @param  vocabulary  localized resources, given because already known by the caller
      *                     (this argument would be removed if this method was public API).
      */
+    @SuppressWarnings("unchecked")
     private void createIsolineTable(final Vocabulary vocabulary) {
         /*
          * First column containing a checkbox for choosing whether the isoline should be drawn or not.
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
index 94966a92ac..3b55a99660 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -252,6 +252,7 @@ public class CoverageCanvas extends MapCanvasAWT {
      * @param  controls  the controls of this canvas, or {@code null} if none.
      * @param  locale    the locale to use for labels and some messages, or {@code null} for default.
      */
+    @SuppressWarnings("this-escape")
     CoverageCanvas(final CoverageControls controls, final Locale locale) {
         super(locale);
         this.controls         = controls;
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
index e9086e38c6..f5ea4e2206 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
@@ -147,9 +147,9 @@ final class CoverageControls extends ViewAndControls {
             final ValueColorMapper mapper = new ValueColorMapper(resources, vocabulary);
             isolines = new IsolineRenderer(view);
             isolines.setIsolineTables(List.of(mapper.getSteps()));
-            final Region view = mapper.getView();
-            VBox.setVgrow(view, Priority.ALWAYS);
-            isolinesPane = new VBox(view);                          // TODO: add band selector
+            final Region style = mapper.getView();
+            VBox.setVgrow(style, Priority.ALWAYS);
+            isolinesPane = new VBox(style);                         // TODO: add band selector
         }
         /*
          * Synchronized windows. A synchronized windows is a window which can reproduce the same gestures
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
index 0f1da54034..88486ce894 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
@@ -229,6 +229,7 @@ public class CoverageExplorer extends Widget {
      *
      * @since 1.2
      */
+    @SuppressWarnings("this-escape")
     public CoverageExplorer(final View type) {
         ArgumentChecks.ensureNonNull("type", type);
         views            = new EnumMap<>(View.class);
@@ -250,6 +251,7 @@ public class CoverageExplorer extends Widget {
      *
      * @since 1.2
      */
+    @SuppressWarnings("this-escape")
     public CoverageExplorer(final CoverageExplorer source) {
         this(source.getViewType());
         window = PrivateAccess.newWindowHandler.apply(source.window, this);
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageStyling.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageStyling.java
index f41a557a66..6841dd17dc 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageStyling.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageStyling.java
@@ -64,7 +64,6 @@ final class CoverageStyling extends ColorColumnHandler<Category> implements Func
     /**
      * Creates a new styling instance.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     CoverageStyling(final CoverageCanvas canvas) {
         customizedColors = new HashMap<>();
         this.canvas = canvas;
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridViewSkin.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridViewSkin.java
index 9b3dedd400..9ba58d8854 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridViewSkin.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridViewSkin.java
@@ -426,7 +426,6 @@ final class GridViewSkin extends VirtualContainerBase<GridView, GridRow> impleme
          * Creates a new flow for the given view. This method registers listeners
          * on the properties that may require a redrawn of the full view port.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         Flow(final GridView view) {
             setPannable(false);         // We will use our own pan listeners.
             getHbar().valueProperty().addListener(this);
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java
index 2a36af6e64..c9d275d4f7 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java
@@ -152,7 +152,6 @@ final class IsolineRenderer {
          *
          * @param  steps  the list of isoline levels to render.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         Band(final ObservableList<Step> steps) {
             this.steps = steps;
             addListeners(steps);
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
index ce6263bcbd..6774faccb5 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
@@ -142,7 +142,6 @@ public final class PropertyView implements Localized, ChangeListener<Number> {
      * @param  view        the property where to set the node showing the value.
      * @param  background  the image background color, or {@code null} if none.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public PropertyView(final Locale locale, final ObjectProperty<Node> view, final ObjectProperty<Background> background) {
         formats = new PropertyValueFormats(locale);
         this.view = view;
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
index 1738b17ee3..d9863eacfc 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
@@ -46,6 +46,7 @@ import javafx.beans.value.ObservableValue;
 import javafx.beans.value.WritableValue;
 import javafx.concurrent.Task;
 import javafx.concurrent.Worker;
+import javafx.scene.Node;
 import javafx.scene.control.ContextMenu;
 import javafx.scene.control.ToggleGroup;
 import javafx.scene.transform.Affine;
@@ -351,6 +352,7 @@ public abstract class MapCanvas extends PlanarCanvas {
      *
      * @param  locale  the locale to use for labels and some messages, or {@code null} for default.
      */
+    @SuppressWarnings("this-escape")
     public MapCanvas(final Locale locale) {
         super(locale);
         transform        = new Affine();
@@ -719,7 +721,6 @@ public abstract class MapCanvas extends PlanarCanvas {
          * Creates and registers a new handler for showing a contextual menu in the enclosing canvas.
          * It is caller responsibility to ensure that this method is invoked only once.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         MenuHandler(final ContextMenu menu) {
             super(getDisplayCRS());
             this.menu = menu;
@@ -737,7 +738,7 @@ public abstract class MapCanvas extends PlanarCanvas {
                 hideContextMenu();
                 x = event.getX();
                 y = event.getY();
-                menu.show((Pane) event.getSource(), event.getScreenX(), event.getScreenY());
+                menu.show((Node) event.getSource(), event.getScreenX(), event.getScreenY());
                 menuShown = menu;
                 event.consume();
             }
@@ -788,8 +789,8 @@ public abstract class MapCanvas extends PlanarCanvas {
         public void propertyChange(final PropertyChangeEvent event) {
             if (OBJECTIVE_CRS_PROPERTY.equals(event.getPropertyName())) {
                 final Object value = event.getNewValue();
-                if (value instanceof CoordinateReferenceSystem) {
-                    selectedCrsProperty.set((CoordinateReferenceSystem) value);
+                if (value instanceof ReferenceSystem) {
+                    selectedCrsProperty.set((ReferenceSystem) value);
                 }
                 if (!isPositionableProjection) {
                     positionables.selectToggle(null);
@@ -804,8 +805,9 @@ public abstract class MapCanvas extends PlanarCanvas {
      *
      * @param  crs       the new Coordinate Reference System in which to transform all data before displaying.
      * @param  anchor    the point to keep at fixed display coordinates, or {@code null} for default value.
-     * @param  property  the property to reset if the operation fails.
+     * @param  property  the property to reset if the operation fails, or {@code null} if none.
      */
+    @SuppressWarnings("unchecked")
     private void setObjectiveCRS(final CoordinateReferenceSystem crs, DirectPosition anchor,
                                  final ObservableValue<? extends ReferenceSystem> property)
     {
@@ -826,6 +828,7 @@ public abstract class MapCanvas extends PlanarCanvas {
             requestRepaint();
         } catch (Exception e) {
             if (property instanceof WritableValue<?>) {
+                // Cast is ok because used only for properties that we defined.
                 ((WritableValue<ReferenceSystem>) property).setValue(previous);
             }
             errorOccurred(e);
@@ -1212,6 +1215,7 @@ public abstract class MapCanvas extends PlanarCanvas {
                      * Otherwise the transform is initialized to an identity transform (should not happen often).
                      * If a CRS is present, it is used for deciding if we need to swap or flip axes.
                      */
+                    @SuppressWarnings("LocalVariableHidesMemberVariable")
                     final Envelope objectiveBounds = getObjectiveBounds();
                     if (objectiveBounds != null) {
                         final MatrixSIS m;
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvasAWT.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvasAWT.java
index d27ab815ae..b72e067ba7 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvasAWT.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvasAWT.java
@@ -153,6 +153,7 @@ public abstract class MapCanvasAWT extends MapCanvas {
      *
      * @param  locale  the locale to use for labels and some messages, or {@code null} for default.
      */
+    @SuppressWarnings("this-escape")
     public MapCanvasAWT(final Locale locale) {
         super(locale);
         imageMargin = new SimpleObjectProperty<>(this, "imageMargin", DEFAULT_MARGIN);
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java
index a1b1af05fb..8da1947388 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataTree.java
@@ -180,6 +180,7 @@ check:      if (data != null) {
      *
      * @param  controller  the widget to watch, or {@code null} if none.
      */
+    @SuppressWarnings("this-escape")
     public MetadataTree(final MetadataSummary controller) {
         this(controller, false);
         setRowFactory(Row::new);
@@ -192,7 +193,7 @@ check:      if (data != null) {
      * @param  controller  the widget to watch, or {@code null} if none.
      * @param  standard    {@code true} for showing standard metadata, or {@code false} for native metadata.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
+    @SuppressWarnings({"this-escape", "unchecked"})
     MetadataTree(final MetadataSummary controller, final boolean standard) {
         final Vocabulary vocabulary;
         if (controller != null) {
@@ -405,7 +406,6 @@ check:      if (data != null) {
         /**
          * Creates a new row for the given tree table.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         Row(final TreeTableView<TreeTable.Node> owner) {
             final MetadataTree md = (MetadataTree) owner;
             final Resources localized = Resources.forLocale(md.getLocale());
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java
index b40e00a40e..56b73d5c0f 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/StandardMetadataTree.java
@@ -127,7 +127,6 @@ public class StandardMetadataTree extends MetadataTree {
         /**
          * Creates a new row for the given tree table.
          */
-        @SuppressWarnings("ThisEscapedInObjectConstruction")
         Row(final TreeTableView<TreeTable.Node> view) {
             super(view);
             final StandardMetadataTree md = (StandardMetadataTree) view;
diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
index 6a770d3bc5..7d9622e9ba 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
@@ -71,7 +71,6 @@ final class WKTPane extends StringConverter<Convention> implements ChangeListene
     /**
      * Creates a new pane for showing CRS Well Known Text.
      */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
     WKTPane(final Locale locale) {
         final Convention[] sc = {           // Selected conventions in the order we want them to appear.
             Convention.WKT2_SIMPLIFIED,


(sis) 03/03: Deprecate `ArgumentChecks` methods that are replaced by Java 9 methods: - `ensureValidIndex`, replaced by `Objects.checkIndex`. - `ensureValidIndexRange`, replaced by `Objects.checkFromToIndex`.

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 938b35b5e45c748c141ec48f0d8589c13d4f23f9
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Feb 6 19:08:04 2024 +0100

    Deprecate `ArgumentChecks` methods that are replaced by Java 9 methods:
    - `ensureValidIndex`, replaced by `Objects.checkIndex`.
    - `ensureValidIndexRange`, replaced by `Objects.checkFromToIndex`.
    
    Some `ensureNonNull` are also either removed (now that Java produces a good error message by itself) or replaced by `Objects.requireNonNull`.
---
 .../main/org/apache/sis/coverage/Category.java     |  1 +
 .../main/org/apache/sis/coverage/CategoryList.java |  4 +++-
 .../org/apache/sis/coverage/CoverageCombiner.java  |  2 --
 .../org/apache/sis/coverage/SampleDimension.java   |  6 ++----
 .../apache/sis/coverage/grid/DefaultEvaluator.java |  6 ++----
 .../sis/coverage/grid/DimensionalityReduction.java | 10 +++-------
 .../apache/sis/coverage/grid/DomainLinearizer.java |  2 --
 .../sis/coverage/grid/GridCoordinatesView.java     |  5 ++---
 .../org/apache/sis/coverage/grid/GridExtent.java   | 21 +++++++++------------
 .../org/apache/sis/coverage/grid/GridGeometry.java |  4 ++--
 .../apache/sis/xml/bind/lan/LocaleAndCharset.java  |  4 ++--
 .../org/apache/sis/geometry/ArrayEnvelope.java     | 18 ++++++------------
 .../org/apache/sis/geometry/GeneralEnvelope.java   | 22 +++-------------------
 .../main/org/apache/sis/geometry/SubEnvelope.java  | 14 +++++---------
 .../main/org/apache/sis/io/wkt/Warnings.java       |  6 +++---
 .../apache/sis/parameter/ParameterValueList.java   | 17 ++++++-----------
 .../main/org/apache/sis/referencing/CRS.java       |  3 ++-
 .../factory/sql/InstallationScriptProvider.java    |  1 -
 .../operation/builder/LinearTransformBuilder.java  |  4 ++--
 .../sis/referencing/operation/matrix/Matrices.java |  3 +--
 .../referencing/operation/matrix/MatrixSIS.java    | 12 ++++++------
 .../referencing/util/GeodeticObjectBuilder.java    |  4 ++--
 .../main/org/apache/sis/io/LineAppender.java       |  3 ++-
 .../main/org/apache/sis/io/TableAppender.java      |  3 ++-
 .../main/org/apache/sis/math/MathFunctions.java    |  5 ++++-
 .../main/org/apache/sis/math/RepeatedVector.java   |  5 ++---
 .../main/org/apache/sis/math/SequenceVector.java   |  8 +++-----
 .../main/org/apache/sis/math/Vector.java           |  9 ++++-----
 .../main/org/apache/sis/util/ArgumentChecks.java   | 19 ++++++++-----------
 .../main/org/apache/sis/util/CharSequences.java    |  7 ++++---
 .../org/apache/sis/util/collection/Containers.java |  4 ++--
 .../sis/util/collection/DefaultTreeTable.java      |  3 +--
 .../apache/sis/util/collection/IntegerList.java    |  8 ++++----
 .../apache/sis/util/collection/TreeNodeList.java   | 21 ++++++++-------------
 .../sis/util/internal/UnmodifiableArrayList.java   |  6 ++----
 .../apache/sis/map/service/GraphicsPortrayer.java  |  4 ++--
 36 files changed, 110 insertions(+), 164 deletions(-)

diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/Category.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/Category.java
index be97d5cf52..9a6cb13be5 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/Category.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/Category.java
@@ -220,6 +220,7 @@ public class Category implements Serializable {
      * @throws IllegalSampleDimensionException if the {@code samples} range of values is empty
      *         or the transfer function cannot be used.
      */
+    @SuppressWarnings("this-escape")
     protected Category(final CharSequence name, NumberRange<?> samples, final MathTransform1D toUnits, final Unit<?> units,
              final DoubleToIntFunction toNaN)
     {
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CategoryList.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CategoryList.java
index 88a11bbe46..1a2b553584 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CategoryList.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CategoryList.java
@@ -211,8 +211,10 @@ final class CategoryList extends AbstractList<Category> implements MathTransform
         final double[] extremums;
         extremums = new double[count * 2];
         minimums  = new double[count];
-        int countOfFiniteRanges = 0;
+
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         NumberRange<?> range = null;
+        int countOfFiniteRanges = 0;
         for (int i=count; --i >= 0;) {                  // Reverse order for making computation of `range` more convenient.
             final Category category = categories[i];
             if (!isNaN(minimums[i] = category.range.getMinDouble(true))) {
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CoverageCombiner.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CoverageCombiner.java
index 0ca2a6f1c3..79fdf3f924 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CoverageCombiner.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/CoverageCombiner.java
@@ -121,7 +121,6 @@ public class CoverageCombiner {
      * @throws CannotEvaluateException if the coverage does not have at least 2 dimensions.
      */
     public CoverageCombiner(final GridCoverage destination) {
-        ArgumentChecks.ensureNonNull("destination", destination);
         this.destination = destination.forConvertedValues(true);
         isConverted = (this.destination == destination);
         final int[] dim = destination.getGridGeometry().getExtent().getLargestDimensions(BIDIMENSIONAL);
@@ -225,7 +224,6 @@ public class CoverageCombiner {
      *         is not convertible to the unit of measurement of the corresponding target sample dimension.
      */
     public boolean acceptAll(GridCoverage... sources) throws TransformException, IncommensurableException {
-        ArgumentChecks.ensureNonNull("sources", sources);
         sources = sources.clone();
         final GridGeometry        targetGG            = destination.getGridGeometry();
         final GridExtent          targetEx            = targetGG.getExtent();
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleDimension.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleDimension.java
index 3bcb4d329a..8eda32d0e7 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleDimension.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleDimension.java
@@ -1196,14 +1196,12 @@ public class SampleDimension implements Serializable {
 
                 /** Returns the category at the given index. */
                 @Override public Category get(int i) {
-                    ArgumentChecks.ensureValidIndex(count, i);
-                    return categories[i];
+                    return categories[Objects.checkIndex(i, count)];
                 }
 
                 /** Removes the category at the given index. */
                 @Override public Category remove(int i) {
-                    ArgumentChecks.ensureValidIndex(count, i);
-                    final Category c = categories[i];
+                    final Category c = categories[Objects.checkIndex(i, count)];
                     System.arraycopy(categories, i+1, categories, i, --count - i);
                     categories[count] = null;
                     toNaN.remove(c);
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
index 5f8a64f33f..77ee8cf5e3 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
@@ -159,8 +159,7 @@ class DefaultEvaluator implements GridCoverage.Evaluator {
      * @see GridCoverage#evaluator()
      */
     protected DefaultEvaluator(final GridCoverage coverage) {
-        ArgumentChecks.ensureNonNull("coverage", coverage);
-        this.coverage = coverage;
+        this.coverage = Objects.requireNonNull(coverage);
     }
 
     /**
@@ -422,9 +421,8 @@ class DefaultEvaluator implements GridCoverage.Evaluator {
      */
     @Override
     public FractionalGridCoordinates toGridCoordinates(final DirectPosition point) throws TransformException {
-        ArgumentChecks.ensureNonNull("point", point);
         try {
-            return new FractionalGridCoordinates(toGridPosition(point));
+            return new FractionalGridCoordinates(toGridPosition(Objects.requireNonNull(point)));
         } catch (FactoryException e) {
             throw new TransformException(e.getMessage(), e);
         }
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DimensionalityReduction.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DimensionalityReduction.java
index e56317f329..9b0c7ca751 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DimensionalityReduction.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DimensionalityReduction.java
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.HashMap;
 import java.util.Arrays;
 import java.util.BitSet;
+import java.util.Objects;
 import java.util.function.UnaryOperator;
 import java.io.Serializable;
 import org.opengis.util.FactoryException;
@@ -303,8 +304,7 @@ public class DimensionalityReduction implements UnaryOperator<GridCoverage>, Ser
     private static BitSet bitmask(final int[] axes, final int sourceDim) {
         final BitSet bitmask = new BitSet(sourceDim);
         for (final int dim : axes) {
-            ArgumentChecks.ensureValidIndex(sourceDim, dim);
-            bitmask.set(dim);
+            bitmask.set(Objects.checkIndex(dim, sourceDim));
         }
         return bitmask;
     }
@@ -321,7 +321,6 @@ public class DimensionalityReduction implements UnaryOperator<GridCoverage>, Ser
      * @throws IllegalGridGeometryException if the dimensions to keep cannot be separated from the dimensions to omit.
      */
     public static DimensionalityReduction select(final GridGeometry source, final int... gridAxesToPass) {
-        ArgumentChecks.ensureNonNull("source", source);
         final BitSet bitmask = bitmask(gridAxesToPass, source.getDimension());
         try {
             return new DimensionalityReduction(source, bitmask, null);
@@ -362,7 +361,6 @@ public class DimensionalityReduction implements UnaryOperator<GridCoverage>, Ser
      * @throws IllegalGridGeometryException if the dimensions to keep cannot be separated from the dimensions to omit.
      */
     public static DimensionalityReduction remove(final GridGeometry source, final int... gridAxesToRemove) {
-        ArgumentChecks.ensureNonNull("source", source);
         final int sourceDim = source.getDimension();
         final BitSet bitmask = bitmask(gridAxesToRemove, sourceDim);
         bitmask.flip(0, sourceDim);
@@ -385,7 +383,6 @@ public class DimensionalityReduction implements UnaryOperator<GridCoverage>, Ser
      * @see #select2D(GridGeometry)
      */
     public static DimensionalityReduction reduce(final GridGeometry source) {
-        ArgumentChecks.ensureNonNull("source", source);
         final GridExtent extent = source.getExtent();
         final int sourceDim = extent.getDimension();
         final BitSet bitmask = new BitSet(sourceDim);
@@ -732,7 +729,6 @@ public class DimensionalityReduction implements UnaryOperator<GridCoverage>, Ser
      */
     @Override
     public GridCoverage apply(final GridCoverage source) {
-        ArgumentChecks.ensureNonNull("source", source);
         ensureSameAxes(sourceGeometry.extent, source.getGridGeometry().extent);
         if (isIdentity()) return source;
         if (source instanceof DimensionAppender) try {
@@ -942,7 +938,7 @@ public class DimensionalityReduction implements UnaryOperator<GridCoverage>, Ser
      * @throws PointOutsideCoverageException if the given point is outside the source grid extent.
      */
     public DimensionalityReduction withSlicePoint(final long[] point) {
-        ArgumentChecks.ensureNonNull("point", point);
+        Objects.requireNonNull(point);
         final GridExtent extent = sourceGeometry.getExtent();
         final int sourceDim = extent.getDimension();
         ArgumentChecks.ensureDimensionMatches("slicePoint", sourceDim, extent);
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DomainLinearizer.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DomainLinearizer.java
index a9fb085af1..2a2533323a 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DomainLinearizer.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DomainLinearizer.java
@@ -142,7 +142,6 @@ public class DomainLinearizer {
      * @throws TransformException if some cell coordinates cannot be computed.
      */
     public GridCoverage apply(final GridCoverage coverage) throws TransformException {
-        ArgumentChecks.ensureNonNull("coverage", coverage);
         final GridGeometry gg = coverage.getGridGeometry();
         final GridGeometry linearized = apply(gg);
         if (gg.equals(linearized)) {
@@ -164,7 +163,6 @@ public class DomainLinearizer {
      * @throws TransformException if some cell coordinates cannot be computed.
      */
     public GridGeometry apply(final GridGeometry gg) throws TransformException {
-        ArgumentChecks.ensureNonNull("gg", gg);
         if (gg.nonLinears != 0) try {
             MathTransform   gridToCRS   = gg.requireGridToCRS(true);
             GeneralEnvelope domain      = gg.extent.toEnvelope();
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoordinatesView.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoordinatesView.java
index 2127cef69d..52885418fd 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoordinatesView.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoordinatesView.java
@@ -17,7 +17,7 @@
 package org.apache.sis.coverage.grid;
 
 import java.util.Arrays;
-import org.apache.sis.util.ArgumentChecks;
+import java.util.Objects;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.coverage.grid.GridCoordinates;
@@ -71,8 +71,7 @@ final class GridCoordinatesView implements GridCoordinates {
      */
     @Override
     public final long getCoordinateValue(final int index) {
-        ArgumentChecks.ensureValidIndex(getDimension(), index);
-        return coordinates[offset + index];
+        return coordinates[offset + Objects.checkIndex(index, getDimension())];
     }
 
     /**
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
index 223d8467ed..b27691017b 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
@@ -26,6 +26,7 @@ import java.io.Serializable;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.awt.Rectangle;
+import java.util.Objects;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
 import org.opengis.geometry.Envelope;
@@ -798,8 +799,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
      */
     @Override
     public long getLow(final int index) {
-        ArgumentChecks.ensureValidIndex(getDimension(), index);
-        return coordinates[index];
+        return coordinates[Objects.checkIndex(index, getDimension())];
     }
 
     /**
@@ -817,8 +817,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
     @Override
     public long getHigh(final int index) {
         final int dimension = getDimension();
-        ArgumentChecks.ensureValidIndex(dimension, index);
-        return coordinates[index + dimension];
+        return coordinates[Objects.checkIndex(index, dimension) + dimension];
     }
 
     /**
@@ -843,8 +842,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
      */
     public long getMedian(final int index) {
         final int dimension = getDimension();
-        ArgumentChecks.ensureValidIndex(dimension, index);
-        final long low  = coordinates[index];
+        final long low  = coordinates[Objects.checkIndex(index, dimension)];
         final long high = coordinates[index + dimension];
         /*
          * Use `>> 1` instead of `/2` because the two operations differ in their rounding mode for negative values.
@@ -898,7 +896,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
     @Override
     public long getSize(final int index) {
         final int dimension = getDimension();
-        ArgumentChecks.ensureValidIndex(dimension, index);
+        Objects.checkIndex(index, dimension);
         return Math.incrementExact(Math.subtractExact(coordinates[dimension + index], coordinates[index]));
     }
 
@@ -914,7 +912,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
      */
     public double getSize(final int index, final boolean minusOne) {
         final int dimension = getDimension();
-        ArgumentChecks.ensureValidIndex(dimension, index);
+        Objects.checkIndex(index, dimension);
         long size = coordinates[dimension + index] - coordinates[index];        // Unsigned long.
         if (!minusOne && ++size == 0) {
             return 0x1P64;                          // Unsigned integer overflow. Result is 2^64.
@@ -1165,7 +1163,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
      *         than the {@linkplain #getDimension() grid dimension}.
      */
     public Optional<DimensionNameType> getAxisType(final int index) {
-        ArgumentChecks.ensureValidIndex(getDimension(), index);
+        Objects.checkIndex(index, getDimension());
         return Optional.ofNullable((types != null) ? types[index] : null);
     }
 
@@ -1211,8 +1209,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
      */
     public GridExtent withRange(final int index, final long low, final long high) {
         int ih = getDimension();
-        ArgumentChecks.ensureValidIndex(ih, index);
-        ih += index;
+        ih += Objects.checkIndex(index, ih);
         if (coordinates[index] == low && coordinates[ih] == high) {
             return this;
         }
@@ -1422,7 +1419,7 @@ public class GridExtent implements GridEnvelope, LenientComparable, Serializable
      */
     public GridExtent insertDimension(final int index, final DimensionNameType axisType, final long low, long high, final boolean isHighIncluded) {
         final int dimension = getDimension();
-        ArgumentChecks.ensureValidIndex(dimension+1, index);
+        Objects.checkIndex(index, dimension+1);
         if (!isHighIncluded) {
             high = Math.decrementExact(high);
         }
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
index c532eab0c2..3e3f3823f5 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
@@ -17,6 +17,7 @@
 package org.apache.sis.coverage.grid;
 
 import java.util.Locale;
+import java.util.Objects;
 import java.util.Optional;
 import java.time.Instant;
 import java.text.NumberFormat;
@@ -1244,8 +1245,7 @@ public class GridGeometry implements LenientComparable, Serializable {
         final int dimension = getTargetDimension();
         long mask = 0;
         for (final int d : targets) {
-            ArgumentChecks.ensureValidIndex(dimension, d);
-            mask |= Numerics.bitmask(d);
+            mask |= Numerics.bitmask(Objects.checkIndex(d, dimension));
         }
         return (nonLinears & mask) == 0;
     }
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java
index 5cbea92b82..40cddf718d 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/lan/LocaleAndCharset.java
@@ -24,8 +24,8 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Locale;
 import java.util.Iterator;
+import java.util.Objects;
 import java.nio.charset.Charset;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.internal.Bag;
 import org.apache.sis.util.internal.Unsafe;
 import org.apache.sis.util.internal.CollectionsExt;
@@ -179,7 +179,7 @@ public final class LocaleAndCharset implements Node {
 
             /** Returns a child node wrapping the {@link Charset} ad the given index. */
             @Override public Node get(final int index) {
-                ArgumentChecks.ensureValidIndex(1, index);
+                Objects.checkIndex(index, 1);
                 return new Child();
             }
         };
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/ArrayEnvelope.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/ArrayEnvelope.java
index 7d1543b99d..0eac36ed68 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/ArrayEnvelope.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/ArrayEnvelope.java
@@ -439,8 +439,7 @@ scanNumber: while ((i += Character.charCount(c)) < length) {
      */
     @Override                                       // Must also be overridden in SubEnvelope
     public double getLower(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(coordinates.length >>> 1, dimension);
-        return coordinates[dimension];
+        return coordinates[Objects.checkIndex(dimension, coordinates.length >>> 1)];
     }
 
     /**
@@ -449,8 +448,7 @@ scanNumber: while ((i += Character.charCount(c)) < length) {
     @Override                                       // Must also be overridden in SubEnvelope
     public double getUpper(final int dimension) throws IndexOutOfBoundsException {
         final int d = coordinates.length >>> 1;
-        ensureValidIndex(d, dimension);
-        return coordinates[dimension + d];
+        return coordinates[Objects.checkIndex(dimension, d) + d];
     }
 
     /**
@@ -458,8 +456,7 @@ scanNumber: while ((i += Character.charCount(c)) < length) {
      */
     @Override
     public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(endIndex(), dimension);
-        final int i = dimension + beginIndex();
+        final int i = Objects.checkIndex(dimension, endIndex()) + beginIndex();
         double lower = coordinates[i];
         if (isNegative(coordinates[i + (coordinates.length >>> 1)] - lower)) {    // Special handling for -0.0
             final CoordinateSystemAxis axis = getAxis(crs, dimension);
@@ -473,8 +470,7 @@ scanNumber: while ((i += Character.charCount(c)) < length) {
      */
     @Override
     public double getMaximum(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(endIndex(), dimension);
-        final int i = dimension + beginIndex();
+        final int i = Objects.checkIndex(dimension, endIndex()) + beginIndex();
         double upper = coordinates[i + (coordinates.length >>> 1)];
         if (isNegative(upper - coordinates[i])) {                               // Special handling for -0.0
             final CoordinateSystemAxis axis = getAxis(crs, dimension);
@@ -488,8 +484,7 @@ scanNumber: while ((i += Character.charCount(c)) < length) {
      */
     @Override
     public double getMedian(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(endIndex(), dimension);
-        final int i = dimension + beginIndex();
+        final int i = Objects.checkIndex(dimension, endIndex()) + beginIndex();
         final double minimum = coordinates[i];
         final double maximum = coordinates[i + (coordinates.length >>> 1)];
         double median = 0.5 * (minimum + maximum);
@@ -504,8 +499,7 @@ scanNumber: while ((i += Character.charCount(c)) < length) {
      */
     @Override
     public double getSpan(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(endIndex(), dimension);
-        final int i = dimension + beginIndex();
+        final int i = Objects.checkIndex(dimension, endIndex()) + beginIndex();
         double span = coordinates[i + (coordinates.length >>> 1)] - coordinates[i];
         if (isNegative(span)) {                                                 // Special handling for -0.0
             span = fixSpan(getAxis(crs, dimension), span);
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/GeneralEnvelope.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/GeneralEnvelope.java
index 3e20d998f9..3d00c8f948 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/GeneralEnvelope.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/GeneralEnvelope.java
@@ -24,6 +24,7 @@ package org.apache.sis.geometry;
  */
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.Objects;
 import java.time.Instant;
 import java.io.Serializable;
 import java.lang.reflect.Field;
@@ -340,7 +341,7 @@ public class GeneralEnvelope extends ArrayEnvelope implements Cloneable, Seriali
             throws IndexOutOfBoundsException
     {
         final int d = coordinates.length >>> 1;
-        ensureValidIndex(d, dimension);
+        Objects.checkIndex(dimension, d);
         /*
          * The check performed here shall be identical to ArrayEnvelope.verifyRanges(crs, coordinates),
          * except that there is no loop.
@@ -524,23 +525,6 @@ public class GeneralEnvelope extends ArrayEnvelope implements Cloneable, Seriali
         }
     }
 
-    /**
-     * Adds to this envelope a point of the given array.
-     * This method does not check for anti-meridian crossing. It is invoked only
-     * by the {@link Envelopes} transform methods, which build "normal" envelopes.
-     *
-     * @param  array   the array which contains the coordinate values.
-     * @param  offset  index of the first valid coordinate value in the given array.
-     */
-    final void addSimple(final double[] array, final int offset) {
-        final int d = coordinates.length >>> 1;
-        for (int i=0; i<d; i++) {
-            final double value = array[offset + i];
-            if (value < coordinates[i  ]) coordinates[i  ] = value;
-            if (value > coordinates[i+d]) coordinates[i+d] = value;
-        }
-    }
-
     /**
      * Adds a point to this envelope. The resulting envelope is the smallest envelope that
      * contains both the original envelope and the specified point.
@@ -1267,7 +1251,7 @@ public class GeneralEnvelope extends ArrayEnvelope implements Cloneable, Seriali
      */
     // Must be overridden in SubEnvelope
     public GeneralEnvelope subEnvelope(final int beginIndex, final int endIndex) throws IndexOutOfBoundsException {
-        ensureValidIndexRange(coordinates.length >>> 1, beginIndex, endIndex);
+        Objects.checkFromToIndex(beginIndex, endIndex, coordinates.length >>> 1);
         return new SubEnvelope(coordinates, beginIndex, endIndex);
         /*
          * Do not check if we could return "this" as an optimization, in order to keep
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/SubEnvelope.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/SubEnvelope.java
index 54eea5d3d6..7d34fe120e 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/SubEnvelope.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/SubEnvelope.java
@@ -23,9 +23,7 @@ package org.apache.sis.geometry;
  * force installation of the Java2D module (e.g. JavaFX/SWT).
  */
 import java.util.Arrays;
-
-import static org.apache.sis.util.ArgumentChecks.ensureValidIndex;
-import static org.apache.sis.util.ArgumentChecks.ensureValidIndexRange;
+import java.util.Objects;
 
 
 /**
@@ -102,8 +100,7 @@ final class SubEnvelope extends GeneralEnvelope {
      */
     @Override
     public double getLower(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(endIndex, dimension);
-        return coordinates[dimension + beginIndex];
+        return coordinates[Objects.checkIndex(dimension, endIndex) + beginIndex];
     }
 
     /**
@@ -112,8 +109,7 @@ final class SubEnvelope extends GeneralEnvelope {
      */
     @Override
     public double getUpper(final int dimension) throws IndexOutOfBoundsException {
-        ensureValidIndex(endIndex, dimension);
-        return coordinates[dimension + beginIndex + (coordinates.length >>> 1)];
+        return coordinates[Objects.checkIndex(dimension, endIndex) + beginIndex + (coordinates.length >>> 1)];
     }
 
     /**
@@ -123,7 +119,7 @@ final class SubEnvelope extends GeneralEnvelope {
     public void setRange(int dimension, final double lower, final double upper)
             throws IndexOutOfBoundsException
     {
-        ensureValidIndex(endIndex, dimension);
+        Objects.checkIndex(dimension, endIndex);
         /*
          * The check performed here shall be identical to the super-class method, which is itself
          * identical to ArrayEnvelope.verifyRanges(crs, coordinates) except that there is no loop.
@@ -197,7 +193,7 @@ final class SubEnvelope extends GeneralEnvelope {
      */
     @Override
     public GeneralEnvelope subEnvelope(final int b, final int e) throws IndexOutOfBoundsException {
-        ensureValidIndexRange(endIndex - beginIndex, b, e);
+        Objects.checkFromToIndex(b, e, endIndex - beginIndex);
         return new SubEnvelope(coordinates, b + beginIndex, e + beginIndex);
     }
 
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java
index 36e58c4e85..6cd496d503 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Warnings.java
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Iterator;
+import java.util.Objects;
 import java.io.Serializable;
 import org.opengis.metadata.Identifier;
 import org.opengis.referencing.IdentifiedObject;
@@ -32,7 +33,6 @@ import org.opengis.util.InternationalString;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.Localized;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Messages;
 import org.apache.sis.util.resources.Vocabulary;
@@ -243,7 +243,7 @@ public final class Warnings implements Localized, Serializable {
      * @return the <var>i</var>-th warning message.
      */
     public String getMessage(int index) {
-        ArgumentChecks.ensureValidIndex(getNumMessages(), index);
+        Objects.checkIndex(index, getNumMessages());
         index *= 2;
         final InternationalString i18n = (InternationalString) messages.get(index);
         if (i18n != null) {
@@ -266,7 +266,7 @@ public final class Warnings implements Localized, Serializable {
      * @return the exception which was the cause of the warning message, or {@code null} if none.
      */
     public Exception getException(final int index) {
-        ArgumentChecks.ensureValidIndex(getNumMessages(), index);
+        Objects.checkIndex(index, getNumMessages());
         return (Exception) messages.get(index*2 + 1);
     }
 
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterValueList.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterValueList.java
index 1263bac902..7c558bd6c0 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterValueList.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterValueList.java
@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.AbstractList;
 import java.util.RandomAccess;
 import java.util.Arrays;
+import java.util.Objects;
 import java.io.Serializable;
 import java.io.IOException;
 import java.io.ObjectOutputStream;
@@ -32,7 +33,6 @@ import org.opengis.parameter.InvalidParameterNameException;
 import org.opengis.parameter.InvalidParameterCardinalityException;
 import org.opengis.metadata.Identifier;
 import org.apache.sis.util.ArraysExt;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.internal.Resources;
@@ -145,8 +145,7 @@ final class ParameterValueList extends AbstractList<GeneralParameterValue> imple
      */
     @Override
     public GeneralParameterValue get(int index) {
-        ArgumentChecks.ensureValidIndex(size, index);
-        GeneralParameterValue value = values[index];
+        GeneralParameterValue value = values[Objects.checkIndex(index, size)];
         if (value instanceof UninitializedParameter) {
             values[index] = value = value.getDescriptor().createValue();
         }
@@ -160,9 +159,7 @@ final class ParameterValueList extends AbstractList<GeneralParameterValue> imple
      */
     @Override
     public GeneralParameterValue set(final int index, final GeneralParameterValue parameter) {
-        ArgumentChecks.ensureValidIndex(size, index);
-        final GeneralParameterValue value = values[index];
-        ArgumentChecks.ensureNonNull("parameter", parameter);
+        final GeneralParameterValue value = values[Objects.checkIndex(index, size)];
         final GeneralParameterDescriptor desc = parameter.getDescriptor();
         if (!value.getDescriptor().equals(desc)) {
             ensureDescriptorExists(desc);
@@ -187,7 +184,6 @@ final class ParameterValueList extends AbstractList<GeneralParameterValue> imple
      */
     @Override
     public boolean add(final GeneralParameterValue parameter) {
-        ArgumentChecks.ensureNonNull("parameter", parameter);
         final GeneralParameterDescriptor desc = parameter.getDescriptor();
         ensureDescriptorExists(desc);
         /*
@@ -241,8 +237,8 @@ final class ParameterValueList extends AbstractList<GeneralParameterValue> imple
              */
             final Identifier name = desc.getName();
             final String code = name.getCode();
-            for (final GeneralParameterDescriptor descriptor : descriptors) {
-                if (IdentifiedObjects.isHeuristicMatchForName(descriptor, code)) {
+            for (final GeneralParameterDescriptor d : descriptors) {
+                if (IdentifiedObjects.isHeuristicMatchForName(d, code)) {
                     throw new IllegalArgumentException(Resources.format(
                             Resources.Keys.MismatchedParameterDescriptor_1, name));
                 }
@@ -303,8 +299,7 @@ final class ParameterValueList extends AbstractList<GeneralParameterValue> imple
      */
     @Override
     public GeneralParameterValue remove(final int index) {
-        ArgumentChecks.ensureValidIndex(size, index);
-        final GeneralParameterValue value = values[index];
+        final GeneralParameterValue value = values[Objects.checkIndex(index, size)];
         ensureCanRemove(value.getDescriptor());
         System.arraycopy(values, index + 1, values, index, --size - index);
         values[size] = null;
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index 7bd5854b2d..e367036ff2 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
@@ -19,6 +19,7 @@ package org.apache.sis.referencing;
 import java.util.Map;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.logging.Filter;
 import java.util.logging.Logger;
@@ -1460,7 +1461,7 @@ public final class CRS extends Static {
     public static CoordinateReferenceSystem getComponentAt(CoordinateReferenceSystem crs, int lower, int upper) {
         if (crs == null) return null;     // Skip bounds check.
         int dimension = ReferencingUtilities.getDimension(crs);
-        ArgumentChecks.ensureValidIndexRange(dimension, lower, upper);
+        Objects.checkFromToIndex(lower, upper, dimension);
 check:  while (lower != 0 || upper != dimension) {
             if (crs instanceof CompoundCRS) {
                 // We need nested CompoundCRS (if any) below, not a flattened list of SingleCRS.
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
index 9cc3708827..51e5802a77 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
@@ -205,7 +205,6 @@ public abstract class InstallationScriptProvider extends InstallationResources {
     @Override
     public BufferedReader openScript(final String authority, final int resource) throws IOException {
         verifyAuthority(authority);
-        ArgumentChecks.ensureValidIndex(resources.length, resource);
         if (!Constants.EPSG.equals(authority)) {
             throw new IllegalStateException(Resources.format(Resources.Keys.UnknownAuthority_1, authority));
         }
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
index 1cae1b466e..9f2c085be4 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
@@ -26,6 +26,7 @@ import java.util.NoSuchElementException;
 import java.util.Optional;
 import java.util.Locale;
 import java.text.NumberFormat;
+import java.util.Objects;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import org.opengis.util.FactoryException;
@@ -1330,8 +1331,7 @@ search:         for (int j=domain(); --j >= 0;) {
             long defined = 0;
             projToGrid = projToGrid.clone();
             for (final int d : projToGrid) {
-                ArgumentChecks.ensureValidIndex(tgtDim, d);
-                if (defined == (defined |= Numerics.bitmask(d))) {
+                if (defined == (defined |= Numerics.bitmask(Objects.checkIndex(d, tgtDim)))) {
                     // Note: if d ≥ 64, there will be no check (mask = 0).
                     throw new IllegalArgumentException(Errors.format(Errors.Keys.DuplicatedNumber_1, d));
                 }
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/Matrices.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/Matrices.java
index 0e1a908f31..ea5432b721 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/Matrices.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/Matrices.java
@@ -577,8 +577,7 @@ public final class Matrices extends Static {
         final int numTargetDim = selectedDimensions.length;
         final MatrixSIS matrix = createZero(numTargetDim+1, sourceDimensions+1);
         for (int j=0; j<numTargetDim; j++) {
-            final int i = selectedDimensions[j];
-            ArgumentChecks.ensureValidIndex(sourceDimensions, i);
+            int i = Objects.checkIndex(selectedDimensions[j], sourceDimensions);
             matrix.setElement(j, i, 1);
         }
         matrix.setElement(numTargetDim, sourceDimensions, 1);
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/MatrixSIS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
index abd0e85050..55c4c0a128 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
@@ -17,12 +17,12 @@
 package org.apache.sis.referencing.operation.matrix;
 
 import java.util.Arrays;
+import java.util.Objects;
 import java.io.Serializable;
 import java.awt.geom.AffineTransform;                       // For javadoc
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.referencing.util.ExtendedPrecisionMatrix;
 import org.apache.sis.referencing.internal.Arithmetic;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.LenientComparable;
 import org.apache.sis.util.Numbers;
@@ -295,7 +295,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
      * @since 0.7
      */
     public void setMatrix(final Matrix source) throws MismatchedMatrixSizeException {
-        ArgumentChecks.ensureNonNull("source", source);
+        Objects.requireNonNull(source);
         final int numRow = getNumRow();
         final int numCol = getNumCol();
         ensureSizeMatch(numRow, numCol, source);
@@ -447,7 +447,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
      */
     public void convertBefore(final int srcDim, final Number scale, final Number offset) {
         final int lastCol = getNumCol() - 1;
-        ArgumentChecks.ensureValidIndex(lastCol, srcDim);
+        Objects.checkIndex(srcDim, lastCol);
         for (int j = getNumRow(); --j >= 0;) {
             if (offset != null) {
                 final Number s = getElementOrNull(j, srcDim);           // Scale factor
@@ -478,7 +478,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
     public void convertAfter(final int tgtDim, final Number scale, final Number offset) {
         final int lastRow = getNumRow() - 1;
         final int lastCol = getNumCol() - 1;
-        ArgumentChecks.ensureValidIndex(lastRow, tgtDim);
+        Objects.checkIndex(tgtDim, lastRow);
         if (scale != null) {
             for (int i=lastCol; i>=0; i--) {
                 final Number s = getElementOrNull(tgtDim, i);
@@ -635,7 +635,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
     public MatrixSIS removeRows(final int lower, final int upper) {
         final int numRow = getNumRow();
         final int numCol = getNumCol();
-        ArgumentChecks.ensureValidIndexRange(numRow, lower, upper);
+        Objects.checkFromToIndex(lower, upper, numRow);
         final MatrixSIS reduced = Matrices.createZero(numRow - (upper - lower), numCol, this);
         int dest = 0;
         for (int j=0; j<numRow; j++) {
@@ -665,7 +665,7 @@ public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable,
     public MatrixSIS removeColumns(final int lower, final int upper) {
         final int numRow = getNumRow();
         final int numCol = getNumCol();
-        ArgumentChecks.ensureValidIndexRange(numCol, lower, upper);
+        Objects.checkFromToIndex(lower, upper, numCol);
         final MatrixSIS reduced = Matrices.createZero(numRow, numCol - (upper - lower), this);
         int dest = 0;
         for (int i=0; i<numCol; i++) {
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/GeodeticObjectBuilder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/GeodeticObjectBuilder.java
index 01ce1f8dfa..55f4214b70 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/GeodeticObjectBuilder.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/GeodeticObjectBuilder.java
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.util;
 import java.util.Map;
 import java.util.Date;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.function.BiConsumer;
 import javax.measure.Unit;
 import javax.measure.quantity.Time;
@@ -256,7 +257,6 @@ public class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder> {
      * @throws FactoryException if the operation method cannot be obtained.
      */
     public GeodeticObjectBuilder setConversion(final ParameterValueGroup parameters) throws FactoryException {
-        ArgumentChecks.ensureNonNull("parameters", parameters);
         method = factories.getCoordinateOperationFactory().getOperationMethod(parameters.getDescriptor().getName().getCode());
         this.parameters = parameters;           // Set only if above line succeed.
         return this;
@@ -634,7 +634,7 @@ public class GeodeticObjectBuilder extends Builder<GeodeticObjectBuilder> {
              */
             return source.equals(replacement) ? source : replacement;
         }
-        ArgumentChecks.ensureValidIndex(srcDim - repDim, firstDimension);
+        Objects.checkIndex(firstDimension, srcDim - repDim);
         if (source instanceof CompoundCRS) {
             final var components = ((CompoundCRS) source).getComponents().toArray(CoordinateReferenceSystem[]::new);
             int lower = 0;
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/LineAppender.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/LineAppender.java
index 31b97de4b6..a749b952b4 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/LineAppender.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/LineAppender.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.io;
 
+import java.util.Objects;
 import java.io.Flushable;
 import java.io.IOException;
 import org.apache.sis.util.Characters;
@@ -577,7 +578,7 @@ split:  for (;;) {
      */
     @Override
     public Appendable append(final CharSequence sequence, int start, final int end) throws IOException {
-        ArgumentChecks.ensureValidIndexRange(sequence.length(), start, end);
+        Objects.checkFromToIndex(start, end, sequence.length());
         if (lineSeparator == null) {
             /*
              * Use the line separator found in the submitted document, if possible.
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java
index 2fad93f5b7..0de68ba745 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java
@@ -19,6 +19,7 @@ package org.apache.sis.io;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.io.Flushable;
 import java.io.IOException;
 import java.io.UncheckedIOException;
@@ -506,7 +507,7 @@ public class TableAppender extends Appender implements Flushable {
     @Override
     @SuppressWarnings("fallthrough")
     public TableAppender append(final CharSequence sequence, int start, int end) {
-        ArgumentChecks.ensureValidIndexRange(sequence.length(), start, end);
+        Objects.checkFromToIndex(start, end, sequence.length());
         if (lineSeparator == null) {
             lineSeparator = lineSeparator(sequence, start, end);
         }
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/MathFunctions.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/MathFunctions.java
index 2d497f6cea..add6f897df 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/MathFunctions.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/MathFunctions.java
@@ -17,6 +17,7 @@
 package org.apache.sis.math;
 
 import java.util.Arrays;
+import java.util.Objects;
 import static java.lang.Math.PI;
 import static java.lang.Math.min;
 import static java.lang.Math.abs;
@@ -797,7 +798,8 @@ public final class MathFunctions extends Static {
      * @see java.math.BigInteger#isProbablePrime(int)
      */
     static int primeNumberAt(final int index) throws IndexOutOfBoundsException {
-        ArgumentChecks.ensureValidIndex(PRIMES_LENGTH_16_BITS, index);
+        Objects.checkIndex(index, PRIMES_LENGTH_16_BITS);
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         short[] primes = MathFunctions.primes;
         if (index >= primes.length) {
             synchronized (MathFunctions.class) {
@@ -842,6 +844,7 @@ testNextNumber:         while (true) {      // Simulate a "goto" statement (usua
      */
     public static int nextPrimeNumber(final int number) throws IllegalArgumentException {
         ArgumentChecks.ensureBetween("number", 2, HIGHEST_SUPPORTED_PRIME_NUMBER, number);
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final short[] primes = MathFunctions.primes;
         int lower = 0;
         int upper = min(PRIMES_LENGTH_15_BITS, primes.length);
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/RepeatedVector.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/RepeatedVector.java
index db30512814..21a3ce8dda 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/RepeatedVector.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/RepeatedVector.java
@@ -17,9 +17,9 @@
 package org.apache.sis.math;
 
 import java.io.Serializable;
+import java.util.Objects;
 import java.util.function.IntSupplier;
 import org.apache.sis.measure.NumberRange;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -119,8 +119,7 @@ final class RepeatedVector extends Vector implements Serializable {
      * Converts the given index from this vector domain to an index in the {@linkplain #base} vector.
      */
     private int toBase(final int index) {
-        ArgumentChecks.ensureValidIndex(size, index);
-        return (index / occurrences) % cycleLength;
+        return (Objects.checkIndex(index, size) / occurrences) % cycleLength;
     }
 
     /**
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/SequenceVector.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/SequenceVector.java
index f3d62960a5..cb809f0935 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/SequenceVector.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/SequenceVector.java
@@ -17,10 +17,10 @@
 package org.apache.sis.math;
 
 import java.util.Arrays;
+import java.util.Objects;
 import java.io.Serializable;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.Numbers;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -190,8 +190,7 @@ abstract class SequenceVector extends Vector implements Serializable {
 
         /** Computes the value at the given index. */
         @Override public final double doubleValue(final int index) {
-            ArgumentChecks.ensureValidIndex(length, index);
-            return Math.fma(index, increment, first);
+            return Math.fma(Objects.checkIndex(index, length), increment, first);
         }
 
         /** Returns the string representation of the value at the given index. */
@@ -318,8 +317,7 @@ abstract class SequenceVector extends Vector implements Serializable {
 
         /** Computes the value at the given index. */
         @Override public long longValue(final int index) {
-            ArgumentChecks.ensureValidIndex(length, index);
-            return first + increment*index;
+            return Math.addExact(first, Math.multiplyExact(increment, Objects.checkIndex(index, length)));
         }
 
         /** Returns the string representation of the value at the given index. */
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/Vector.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/Vector.java
index 81561db4f5..430a8367fc 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/Vector.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/Vector.java
@@ -23,6 +23,7 @@ import java.util.AbstractList;
 import java.util.RandomAccess;
 import java.util.StringJoiner;
 import java.util.Optional;
+import java.util.Objects;
 import java.util.function.IntSupplier;
 import static java.util.logging.Logger.getLogger;
 import org.apache.sis.measure.NumberRange;
@@ -33,7 +34,6 @@ import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.internal.Numerics;
 import org.apache.sis.system.Loggers;
-import static org.apache.sis.util.ArgumentChecks.ensureValidIndex;
 
 
 /**
@@ -560,7 +560,7 @@ public abstract class Vector extends AbstractList<Number> implements RandomAcces
      */
     public void fill(int fromIndex, final int toIndex, final Number value) {
         // Subclasses override with more efficient implementations.
-        ArgumentChecks.ensureValidIndexRange(size(), fromIndex, toIndex);
+        Objects.checkFromToIndex(fromIndex, toIndex, size());
         while (fromIndex < toIndex) set(fromIndex++, value);
     }
 
@@ -967,8 +967,7 @@ search:     for (;;) {
 
         /** Returns the index where to look for the value in the enclosing vector. */
         final int toBacking(final int index) {
-            ensureValidIndex(length, index);
-            return index*step + first;
+            return Objects.checkIndex(index, length) * step + first;
         }
 
         /** Returns the index where to look for the value in the enclosing vector. */
@@ -1105,7 +1104,7 @@ search:     for (;;) {
         indices = indices.clone();
         final int length = size();
         for (int i : indices) {
-            ensureValidIndex(length, i);
+            Objects.checkIndex(i, length);
         }
         return indices;
     }
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java
index 5a0ed48df1..c5e93c7a6d 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java
@@ -59,11 +59,6 @@ import org.opengis.coverage.grid.GridEnvelope;
  *     {@link #ensureCanCast(String, Class, Object) ensureCanCast}.
  *   </td>
  * </tr><tr>
- *   <td>{@link IndexOutOfBoundsException}</td>
- *   <td class="sep">
- *     {@link #ensureValidIndex(int, int) ensureValidIndex}.
- *   </td>
- * </tr><tr>
  *   <td>{@link MismatchedDimensionException}</td>
  *   <td class="sep">
  *     {@link #ensureDimensionMatches(String, int, DirectPosition) ensureDimensionMatches}.
@@ -335,7 +330,10 @@ public final class ArgumentChecks extends Static {
      * @throws IndexOutOfBoundsException if the given index is negative or not lower than the given upper value.
      *
      * @see #ensurePositive(String, int)
+     *
+     * @deprecated As of Java 9, replaced by {@link Objects#checkIndex(int, int)}.
      */
+    @Deprecated(since="1.5", forRemoval=true)
     public static void ensureValidIndex(final int upper, final int index) throws IndexOutOfBoundsException {
         if (index < 0 || index >= upper) {
             throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index));
@@ -359,7 +357,10 @@ public final class ArgumentChecks extends Static {
      *         range is out of the sequence index range.
      *
      * @see #ensureCountBetween(String, boolean, int, int, int)
+     *
+     * @deprecated As of Java 9, replaced by {@link Objects#checkFromToIndex(int, int, int)}.
      */
+    @Deprecated(since="1.5", forRemoval=true)
     public static void ensureValidIndexRange(final int length, final int lower, final int upper) throws IndexOutOfBoundsException {
         if (lower < 0 || upper < lower || upper > length) {
             throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IllegalRange_2, lower, upper));
@@ -369,13 +370,12 @@ public final class ArgumentChecks extends Static {
     /**
      * Ensures that the given integer value is greater than or equals to zero.
      * This method is used for checking values that are <strong>not</strong> index.
-     * For checking index values, use {@link #ensureValidIndex(int, int)} instead.
+     * For checking index values, use {@link Objects#checkIndex(int, int)} instead.
      *
      * @param  name   the name of the argument to be checked, used only if an exception is thrown.
      * @param  value  the user argument to check.
      * @throws IllegalArgumentException if the given value is negative.
      *
-     * @see #ensureValidIndex(int, int)
      * @see #ensureStrictlyPositive(String, int)
      */
     public static void ensurePositive(final String name, final int value)
@@ -568,7 +568,7 @@ public final class ArgumentChecks extends Static {
      * <ul>
      *   <li>{@link #ensureCountBetween(String, boolean, int, int, int) ensureCountBetween(…)}
      *       if the {@code value} argument is a collection size or an array length.</li>
-     *   <li>{@link #ensureValidIndex(int, int) ensureValidIndex(…)} if the {@code value}
+     *   <li>{@link Objects#checkIndex(int, int)} if the {@code value}
      *       argument is an index in a list or an array.</li>
      * </ul>
      *
@@ -579,8 +579,6 @@ public final class ArgumentChecks extends Static {
      * @throws IllegalArgumentException if the given value is not in the given range.
      *
      * @see #ensureCountBetween(String, boolean, int, int, int)
-     * @see #ensureValidIndex(int, int)
-     * @see #ensureValidIndexRange(int, int, int)
      */
     public static void ensureBetween(final String name, final int min, final int max, final int value)
             throws IllegalArgumentException
@@ -660,7 +658,6 @@ public final class ArgumentChecks extends Static {
      * @throws IllegalArgumentException if the given value is not in the given range.
      *
      * @see #ensureBetween(String, int, int, int)
-     * @see #ensureValidIndexRange(int, int, int)
      *
      * @since 1.4
      */
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java
index d39dfce408..33a8a56d48 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java
@@ -17,6 +17,7 @@
 package org.apache.sis.util;
 
 import java.util.Arrays;
+import java.util.Objects;
 import java.nio.CharBuffer;
 import static java.lang.Character.*;
 import org.opengis.metadata.citation.Citation;      // For javadoc
@@ -140,12 +141,12 @@ public final class CharSequences extends Static {
             }
 
             @Override public char charAt(int index) {
-                ArgumentChecks.ensureValidIndex(length, index);
+                Objects.checkIndex(index, length);
                 return ' ';
             }
 
             @Override public CharSequence subSequence(final int start, final int end) {
-                ArgumentChecks.ensureValidIndexRange(length, start, end);
+                Objects.checkFromToIndex(start, end, length);
                 final int n = end - start;
                 return (n == length) ? this : spaces(n);
             }
@@ -981,7 +982,7 @@ search:     for (; fromIndex <= toIndex; fromIndex++) {
      */
     public static CharSequence trimWhitespaces(CharSequence text, int lower, int upper) {
         final int length = length(text);
-        ArgumentChecks.ensureValidIndexRange(length, lower, upper);
+        Objects.checkFromToIndex(lower, upper, length);
         if (text != null) {
             lower = skipLeadingWhitespaces (text, lower, upper);
             upper = skipTrailingWhitespaces(text, lower, upper);
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java
index d2e90b086c..35194b0da3 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java
@@ -21,6 +21,7 @@ import java.util.Set;
 import java.util.List;
 import java.util.Iterator;
 import java.util.Collection;
+import java.util.Objects;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverter;
@@ -118,8 +119,7 @@ public final class Containers extends Static {
      * @throws IndexOutOfBoundsException if the lower or upper value are out of bounds.
      */
     public static <E> List<? extends E> unmodifiableList(final E[] array, final int lower, final int upper) {
-        ArgumentChecks.ensureNonNull("array", array);
-        ArgumentChecks.ensureValidIndexRange(array.length, lower, upper);
+        Objects.checkFromToIndex(lower, upper, array.length);
         return UnmodifiableArrayList.wrap(array, lower, upper);
     }
 
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java
index a8387c81ce..a19c3337d7 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java
@@ -468,8 +468,7 @@ public class DefaultTreeTable implements TreeTable, Cloneable, Serializable {
             this.parent = parent;
             columnIndices = parent.columnIndices;
             final TreeNodeList addTo = (TreeNodeList) parent.getChildren();
-            ArgumentChecks.ensureValidIndex(addTo.size() + 1, index);
-            addTo.addChild(index, this);
+            addTo.addChild(Objects.checkIndex(index, addTo.size() + 1), this);
         }
 
         /**
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java
index 8e49d11435..9d7d998699 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/IntegerList.java
@@ -18,6 +18,7 @@ package org.apache.sis.util.collection;
 
 import java.util.Arrays;
 import java.util.AbstractList;
+import java.util.Objects;
 import java.util.RandomAccess;
 import java.util.Spliterator;
 import java.util.PrimitiveIterator;
@@ -281,8 +282,7 @@ public class IntegerList extends AbstractList<Integer> implements RandomAccess,
      * @throws IndexOutOfBoundsException if the given index is out of bounds.
      */
     public int getInt(final int index) throws IndexOutOfBoundsException {
-        ArgumentChecks.ensureValidIndex(size, index);
-        return getUnchecked(index);
+        return getUnchecked(Objects.checkIndex(index, size));
     }
 
     /**
@@ -333,7 +333,7 @@ public class IntegerList extends AbstractList<Integer> implements RandomAccess,
      * @throws IllegalArgumentException if the given value is out of bounds.
      */
     public void setInt(int index, int value) throws IndexOutOfBoundsException {
-        ArgumentChecks.ensureValidIndex(size, index);
+        Objects.checkIndex(index, size);
         ArgumentChecks.ensureBetween("value", 0, mask, value);
         modCount++;
         setUnchecked(index, value);
@@ -399,7 +399,7 @@ public class IntegerList extends AbstractList<Integer> implements RandomAccess,
      */
     @Override
     protected void removeRange(int lower, int upper) {
-        ArgumentChecks.ensureValidIndexRange(size, lower, upper);
+        Objects.checkFromToIndex(lower, upper, size);
         int lo = lower * bitCount;
         int hi = upper * bitCount;
         final int offset = (lo & OFFSET_MASK);
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeNodeList.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeNodeList.java
index bb91f27c0e..d911c4d8f2 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeNodeList.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeNodeList.java
@@ -18,8 +18,8 @@ package org.apache.sis.util.collection;
 
 import java.util.Arrays;
 import java.util.AbstractList;
+import java.util.Objects;
 import java.io.Serializable;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -163,8 +163,7 @@ abstract class TreeNodeList extends AbstractList<TreeTable.Node>
      */
     @Override
     public TreeTable.Node get(final int index) {
-        ArgumentChecks.ensureValidIndex(size, index);
-        return children[index];
+        return children[Objects.checkIndex(index, size)];
     }
 
     /**
@@ -178,10 +177,8 @@ abstract class TreeNodeList extends AbstractList<TreeTable.Node>
      */
     @Override
     public TreeTable.Node set(final int index, final TreeTable.Node node) throws IllegalArgumentException {
-        ArgumentChecks.ensureValidIndex(size, index);
-        ArgumentChecks.ensureNonNull("node", node);
-        final TreeTable.Node old = children[index];
-        if (old != node) {
+        final TreeTable.Node old = children[Objects.checkIndex(index, size)];
+        if (old != Objects.requireNonNull(node)) {
             if (isParentOf(node)) {
                 ensureNotPresent(node);
                 setParentOf(old, NULL);
@@ -207,9 +204,8 @@ abstract class TreeNodeList extends AbstractList<TreeTable.Node>
      */
     @Override
     public void add(final int index, final TreeTable.Node node) throws IllegalArgumentException {
-        ArgumentChecks.ensureValidIndex(size + 1, index);
-        ArgumentChecks.ensureNonNull("node", node);
-        if (isParentOf(node)) {
+        Objects.checkIndex(index, size + 1);
+        if (isParentOf(Objects.requireNonNull(node))) {
             ensureNotPresent(node);
         } else {
             setParentOf(node, THIS);
@@ -260,7 +256,7 @@ abstract class TreeNodeList extends AbstractList<TreeTable.Node>
      */
     @Override
     protected void removeRange(final int lower, final int upper) throws IllegalArgumentException {
-        ArgumentChecks.ensureValidIndexRange(size, lower, upper);
+        Objects.checkFromToIndex(lower, upper, size);
         int i = upper;
         try {
             while (i != lower) {
@@ -286,8 +282,7 @@ abstract class TreeNodeList extends AbstractList<TreeTable.Node>
      */
     @Override
     public final TreeTable.Node remove(final int index) throws IllegalArgumentException {
-        ArgumentChecks.ensureValidIndex(size, index);
-        final TreeTable.Node old = children[index];
+        final TreeTable.Node old = children[Objects.checkIndex(index, size)];
         setParentOf(old, NULL);
         System.arraycopy(children, index+1, children, index, --size - index);
         children[size] = null;
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java
index 095d97c107..72cc810b8c 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/UnmodifiableArrayList.java
@@ -22,7 +22,6 @@ import java.util.Arrays;
 import java.util.Objects;
 import java.util.RandomAccess;
 import java.lang.reflect.Array;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ConditionallySafe;
 import org.apache.sis.util.collection.CheckedContainer;
 
@@ -303,7 +302,7 @@ public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomA
     public UnmodifiableArrayList<E> subList(final int lower, final int upper)
             throws IndexOutOfBoundsException
     {
-        ArgumentChecks.ensureValidIndexRange(size(), lower, upper);
+        Objects.checkFromToIndex(lower, upper, size());
         return new SubList<>(array, lower + lower(), upper - lower);
     }
 
@@ -357,8 +356,7 @@ public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomA
          */
         @Override
         public E get(final int index) {
-            ArgumentChecks.ensureValidIndex(size, index);
-            return super.get(index + lower);
+            return super.get(Objects.checkIndex(index, size) + lower);
         }
 
         /**
diff --git a/incubator/src/org.apache.sis.portrayal.map/main/org/apache/sis/map/service/GraphicsPortrayer.java b/incubator/src/org.apache.sis.portrayal.map/main/org/apache/sis/map/service/GraphicsPortrayer.java
index f3c383200a..c146d3a81b 100644
--- a/incubator/src/org.apache.sis.portrayal.map/main/org/apache/sis/map/service/GraphicsPortrayer.java
+++ b/incubator/src/org.apache.sis.portrayal.map/main/org/apache/sis/map/service/GraphicsPortrayer.java
@@ -21,6 +21,7 @@ import java.awt.Shape;
 import java.awt.image.BufferedImage;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.ServiceLoader;
 import java.util.stream.Stream;
 import org.apache.sis.coverage.grid.GridCoverage2D;
@@ -29,7 +30,6 @@ import org.apache.sis.map.MapItem;
 import org.apache.sis.map.MapLayer;
 import org.apache.sis.map.MapLayers;
 import org.apache.sis.map.Presentation;
-import org.apache.sis.map.SEPortrayer;
 import org.apache.sis.style.Style;
 import org.apache.sis.util.ArgumentChecks;
 
@@ -92,7 +92,7 @@ public final class GraphicsPortrayer {
         ArgumentChecks.ensureNonNull("domain", domain);
         long[] low = domain.getExtent().getLow().getCoordinateValues();
         for (long l : low) {
-            ArgumentChecks.ensureValidIndex(1, (int) l);
+            Objects.checkIndex((int) l, 1);
         }
 
         this.domain = domain;


(sis) 02/03: Move in `JDK19` internal class the calls to methods that will be replaced by Java 19 method calls when SIS will be allowed to use it.

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 76f2e5a33f4f80e7733eca6e6ffd17b58abcd5ae
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Feb 6 17:14:30 2024 +0100

    Move in `JDK19` internal class the calls to methods that will be replaced by Java 19 method calls when SIS will be allowed to use it.
---
 .../apache/sis/feature/CharacteristicTypeMap.java  |  9 ++++----
 .../org/apache/sis/index/tree/PointTreeTest.java   |  6 ++---
 .../apache/sis/metadata/ModifiableMetadata.java    |  3 ++-
 .../org/apache/sis/metadata/PropertyAccessor.java  |  7 +++---
 .../sis/metadata/iso/extent/DefaultExtent.java     |  4 ++--
 .../org/apache/sis/util/iso/DefaultRecordType.java |  6 ++---
 .../org/apache/sis/util/iso/RecordDefinition.java  |  5 ++---
 .../main/org/apache/sis/util/iso/Types.java        |  5 ++---
 .../apache/sis/xml/bind/IdentifierMapAdapter.java  |  7 +++---
 .../org/apache/sis/parameter/ParameterFormat.java  |  5 ++---
 .../referencing/factory/sql/EPSGCodeFinder.java    | 14 ++++++------
 .../referencing/operation/gridded/GridGroup.java   |  5 ++---
 .../referencing/operation/gridded/LoadedGrid.java  |  5 ++---
 .../sis/referencing/operation/provider/NTv2.java   |  4 ++--
 .../referencing/CC_GeneralOperationParameter.java  |  9 ++++----
 .../referencing/CC_OperationParameterGroup.java    |  6 ++---
 .../apache/sis/storage/netcdf/base/Variable.java   |  4 ++--
 .../sis/storage/netcdf/classic/ChannelDecoder.java |  6 ++---
 .../org/apache/sis/storage/sql/feature/Table.java  |  5 ++---
 .../main/org/apache/sis/storage/FeatureQuery.java  |  8 +++----
 .../apache/sis/storage/event/StoreListeners.java   |  7 +++---
 .../src/org.apache.sis.util/main/module-info.java  |  1 +
 .../main/org/apache/sis/pending/jdk/JDK19.java     | 22 ++++++++++++++++++
 .../main/org/apache/sis/util/Classes.java          |  4 ++--
 .../main/org/apache/sis/util/Locales.java          |  8 +++----
 .../org/apache/sis/util/collection/Containers.java | 26 ++++++++++------------
 .../sis/util/collection/DefaultTreeTable.java      |  6 ++---
 .../apache/sis/util/internal/CollectionsExt.java   |  6 ++---
 .../test/org/apache/sis/test/TestRunner.java       |  4 ++--
 29 files changed, 108 insertions(+), 99 deletions(-)

diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/CharacteristicTypeMap.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/CharacteristicTypeMap.java
index b6a834b27a..9a0285be92 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/CharacteristicTypeMap.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/CharacteristicTypeMap.java
@@ -20,12 +20,12 @@ import java.util.Map;
 import java.util.HashMap;
 import org.opengis.util.ScopedName;
 import org.opengis.util.GenericName;
+import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.internal.AbstractMap;
 import org.apache.sis.util.internal.CollectionsExt;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.collection.WeakValueHashMap;
 import org.apache.sis.util.resources.Errors;
-import static org.apache.sis.util.ArgumentChecks.ensureNonNullElement;
+import org.apache.sis.pending.jdk.JDK19;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.feature.AttributeType;
@@ -109,11 +109,12 @@ final class CharacteristicTypeMap extends AbstractMap<String,AttributeType<?>> {
     private CharacteristicTypeMap(final AttributeType<?> source, final AttributeType<?>[] characterizedBy) {
         this.characterizedBy = characterizedBy;
         int index = 0;
-        final Map<String,Integer> indices = new HashMap<>(Containers.hashMapCapacity(characterizedBy.length));
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
+        final Map<String,Integer> indices = JDK19.newHashMap(characterizedBy.length);
         final Map<String,Integer> aliases = new HashMap<>();
         for (int i=0; i<characterizedBy.length; i++) {
             final AttributeType<?> attribute = characterizedBy[i];
-            ensureNonNullElement("characterizedBy", i, attribute);
+            ArgumentChecks.ensureNonNullElement("characterizedBy", i, attribute);
             GenericName name = attribute.getName();
             String key = AbstractIdentifiedType.toString(name, source, "characterizedBy", i);
             final Integer value = index++;
diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/index/tree/PointTreeTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/index/tree/PointTreeTest.java
index 73614ce88b..1fda032c90 100644
--- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/index/tree/PointTreeTest.java
+++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/index/tree/PointTreeTest.java
@@ -25,11 +25,11 @@ import java.util.Spliterator;
 import org.opengis.geometry.Envelope;
 import org.apache.sis.geometry.Envelope2D;
 import org.apache.sis.geometry.DirectPosition2D;
-import org.apache.sis.util.collection.Containers;
+import org.apache.sis.pending.jdk.JDK19;
 
 // Test dependencies
 import org.junit.Test;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.test.TestUtilities;
@@ -115,7 +115,7 @@ public final class PointTreeTest extends TestCase {
         random = TestUtilities.createRandomNumberGenerator();
         tree = new PointTree<>(Element.class, region, Element::getPosition, 5, false);
         int count = random.nextInt(100) + 200;
-        data = new HashSet<>(Containers.hashMapCapacity(count));
+        data = JDK19.newHashSet(count);
         while (--count >= 0) {
             final Element e = new Element(random);
             assertEquals(data.add(e), tree.add(e));
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/ModifiableMetadata.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/ModifiableMetadata.java
index efc2c3dfdf..e011d2214f 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/ModifiableMetadata.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/ModifiableMetadata.java
@@ -40,6 +40,7 @@ import org.apache.sis.util.internal.CheckedHashSet;
 import org.apache.sis.util.internal.CheckedArrayList;
 import org.apache.sis.metadata.internal.Resources;
 import org.apache.sis.system.Semaphores;
+import org.apache.sis.pending.jdk.JDK19;
 import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
 import static org.apache.sis.metadata.internal.ImplementationHelper.valueIfDefined;
 
@@ -897,7 +898,7 @@ public abstract class ModifiableMetadata extends AbstractMetadata {
             return new EnumMap(keyType);
         } else {
             // Must be LinkedHashMap, not HashMap, because TreeTableView needs stable iteration order.
-            return new LinkedHashMap<>((source != null) ? Containers.hashMapCapacity(source.size()) : 4);
+            return (source != null) ? JDK19.newLinkedHashMap(source.size()) : new LinkedHashMap<>(4);
         }
     }
 
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java
index ebff2363fe..e5ba47e016 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/PropertyAccessor.java
@@ -20,7 +20,6 @@ import java.util.Map;
 import java.util.List;
 import java.util.Arrays;
 import java.util.Locale;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Collection;
 import java.lang.reflect.Method;
@@ -47,11 +46,11 @@ import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.xml.IdentifiedObject;
 import org.apache.sis.measure.ValueRange;
+import org.apache.sis.pending.jdk.JDK19;
 import static org.apache.sis.metadata.PropertyComparator.*;
 import static org.apache.sis.metadata.ValueExistencePolicy.isNullOrEmpty;
 import static org.apache.sis.util.internal.CollectionsExt.snapshot;
 import static org.apache.sis.util.internal.CollectionsExt.modifiableCopy;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
 
 
 /**
@@ -258,7 +257,7 @@ class PropertyAccessor {
         /*
          * Compute all information derived from getters: setters, property names, value types.
          */
-        mapping      = new HashMap<>(hashMapCapacity(allCount));
+        mapping      = JDK19.newHashMap(allCount);
         names        = new String[allCount];
         elementTypes = new Class<?>[allCount];
         Method[] setters = null;
@@ -412,7 +411,7 @@ class PropertyAccessor {
          * Indices map is used for choosing what to do in case of name collision.
          */
         Method[] getters = (MetadataStandard.IMPLEMENTATION_CAN_ALTER_API ? implementation : type).getMethods();
-        final Map<String,Integer> indices = new HashMap<>(hashMapCapacity(getters.length));
+        final Map<String,Integer> indices = JDK19.newHashMap(getters.length);
         boolean hasExtraGetter = false;
         int count = 0;
         for (Method candidate : getters) {
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
index 41a8d8b595..5f4bb57069 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.metadata.iso.extent;
 
-import java.util.Set;
 import java.util.LinkedHashSet;
 import java.util.Collection;
 import java.util.function.BinaryOperator;
@@ -35,6 +34,7 @@ import org.apache.sis.util.Emptiable;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.collection.Containers;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.metadata.TitleProperty;
 import org.apache.sis.metadata.iso.ISOMetadata;
 import org.apache.sis.metadata.internal.ReferencingServices;
@@ -362,7 +362,7 @@ public class DefaultExtent extends ISOMetadata implements Extent {
     private <T> Collection<T> intersect(final Class<T> type, Collection<T> targets, Collection<? extends T> sources, final BinaryOperator<T> intersect) {
         if (!Containers.isNullOrEmpty(sources)) {
             if (!Containers.isNullOrEmpty(targets)) {
-                final Set<T> results = new LinkedHashSet<>(Containers.hashMapCapacity(targets.size()));
+                final LinkedHashSet<T> results = JDK19.newLinkedHashSet(targets.size());
                 T empty = null;
                 for (final T target : targets) {
                     for (final T source : sources) {
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java
index 508c31c49f..1e8f0183f0 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/DefaultRecordType.java
@@ -37,11 +37,11 @@ import org.opengis.util.NameSpace;
 import org.opengis.util.Record;
 import org.opengis.util.RecordType;
 import org.opengis.util.RecordSchema;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ObjectConverters;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.converter.SurjectiveConverter;
 import org.apache.sis.metadata.internal.RecordSchemaSIS;
 
@@ -203,7 +203,7 @@ public class DefaultRecordType extends RecordDefinition implements RecordType, S
         this.typeName  = typeName;
         this.container = container;
         final NameSpace namespace = nameFactory.createNameSpace(typeName, null);
-        final Map<MemberName,Type> fieldTypes = new LinkedHashMap<>(Containers.hashMapCapacity(fields.size()));
+        final Map<MemberName,Type> fieldTypes = JDK19.newLinkedHashMap(fields.size());
         for (final Map.Entry<? extends CharSequence, ? extends Type> entry : fields.entrySet()) {
             final Type         type   = entry.getValue();
             final CharSequence name   = entry.getKey();
@@ -226,7 +226,7 @@ public class DefaultRecordType extends RecordDefinition implements RecordType, S
     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
         final int size = in.readInt();
-        final Map<MemberName,Type> fields = new LinkedHashMap<>(Containers.hashMapCapacity(size));
+        final Map<MemberName,Type> fields = JDK19.newLinkedHashMap(size);
         for (int i=0; i<size; i++) {
             final MemberName member = (MemberName) in.readObject();
             final Type type = (Type) in.readObject();
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/RecordDefinition.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/RecordDefinition.java
index f88ed7bae9..e7f78fe005 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/RecordDefinition.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/RecordDefinition.java
@@ -17,7 +17,6 @@
 package org.apache.sis.util.iso;
 
 import java.util.Map;
-import java.util.LinkedHashMap;
 import java.io.Serializable;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -29,8 +28,8 @@ import org.opengis.util.MemberName;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.internal.CollectionsExt;
+import org.apache.sis.pending.jdk.JDK19;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.feature.AttributeType;
@@ -147,7 +146,7 @@ abstract class RecordDefinition {                                       // Inten
     final Type[] computeTransientFields(final Map<? extends MemberName, ? extends Type> fieldTypes) {
         final int size = fieldTypes.size();
         fieldNames   = new MemberName[size];
-        fieldIndices = new LinkedHashMap<>(Containers.hashMapCapacity(size));
+        fieldIndices = JDK19.newLinkedHashMap(size);
         final Type[] types = new Type[size];
         int i = 0;
         for (final Map.Entry<? extends MemberName, ? extends Type> entry : fieldTypes.entrySet()) {
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
index b55246f6f9..fd499b6157 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
@@ -17,7 +17,6 @@
 package org.apache.sis.util.iso;
 
 import java.util.Map;
-import java.util.HashMap;
 import java.util.SortedMap;
 import java.util.Locale;
 import java.util.Properties;
@@ -42,9 +41,9 @@ import org.apache.sis.util.OptionalCandidate;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Messages;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.internal.CodeLists;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.system.Modules;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -525,7 +524,7 @@ public final class Types extends Static {
              * Also use internized strings because those Strings are programmatic names or annotation values
              * which are expected to be internized anyway when the corresponding classes are loaded.
              */
-            typeForNames = new HashMap<>(Containers.hashMapCapacity(2 * props.size()));
+            typeForNames = JDK19.newHashMap(2 * props.size());
             for (final Map.Entry<Object,Object> e : props.entrySet()) {
                 final String key   = ((String) e.getKey()).intern();
                 final String value = ((String) e.getValue()).intern();
diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/IdentifierMapAdapter.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/IdentifierMapAdapter.java
index 23528e0bca..7e7fb7e8d0 100644
--- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/IdentifierMapAdapter.java
+++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/IdentifierMapAdapter.java
@@ -34,7 +34,8 @@ import org.apache.sis.xml.IdentifierMap;
 import org.apache.sis.xml.IdentifierSpace;
 import org.apache.sis.util.internal.Strings;
 import org.apache.sis.util.internal.SetOfUnknownSize;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
+import org.apache.sis.util.collection.Containers;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -212,7 +213,7 @@ public class IdentifierMapAdapter extends AbstractMap<Citation,String> implement
      */
     @Override
     public final int size() {
-        final HashSet<Citation> done = new HashSet<>(hashMapCapacity(identifiers.size()));
+        final HashSet<Citation> done = JDK19.newHashSet(identifiers.size());
         for (final Identifier identifier : identifiers) {
             if (identifier != null) {
                 done.add(identifier.getAuthority());
@@ -442,7 +443,7 @@ public class IdentifierMapAdapter extends AbstractMap<Citation,String> implement
          * Creates a new iterator for the given collection of identifiers.
          */
         Iter(final Collection<? extends Identifier> identifiers, final boolean isModifiable) {
-            super(hashMapCapacity(identifiers.size()));
+            super(Containers.hashMapCapacity(identifiers.size()));
             this.identifiers = identifiers.iterator();
             this.isModifiable = isModifiable;
         }
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
index 0fde2b164e..0e59fb3865 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
@@ -56,7 +56,7 @@ import org.apache.sis.util.internal.CollectionsExt;
 import org.apache.sis.util.internal.X364;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.metadata.internal.NameToIdentifier;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
+import org.apache.sis.pending.jdk.JDK19;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.util.ControlledVocabulary;
@@ -462,8 +462,7 @@ public class ParameterFormat extends TabularFormat<Object> {
          */
         int codespaceWidth = 0;
         final Collection<?> elements = (values != null) ? values.values() : group.descriptors();
-        final Map<GeneralParameterDescriptor, ParameterTableRow> descriptorValues =
-                new LinkedHashMap<>(hashMapCapacity(elements.size()));
+        final Map<GeneralParameterDescriptor, ParameterTableRow> descriptorValues = JDK19.newLinkedHashMap(elements.size());
         List<Object> deferredGroups = null;                 // To be created only if needed (it is usually not).
         for (final Object element : elements) {
             final GeneralParameterValue parameter;
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java
index 9390894ab0..1aea9d2f61 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java
@@ -40,18 +40,18 @@ import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.datum.TemporalDatum;
 import org.opengis.referencing.datum.VerticalDatum;
 import org.opengis.referencing.datum.VerticalDatumType;
-import org.apache.sis.metadata.internal.ReferencingServices;
-import org.apache.sis.metadata.sql.util.SQLUtilities;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.referencing.util.Formulas;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.internal.CollectionsExt;
+import org.apache.sis.pending.jdk.JDK19;
+import org.apache.sis.metadata.internal.ReferencingServices;
+import org.apache.sis.metadata.sql.util.SQLUtilities;
 import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.util.Formulas;
 import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
 import org.apache.sis.referencing.factory.ConcurrentAuthorityFactory;
-import org.apache.sis.util.collection.Containers;
-import org.apache.sis.util.logging.Logging;
 import static org.apache.sis.metadata.internal.NameToIdentifier.Simplifier.ESRI_DATUM_PREFIX;
 
 
@@ -134,7 +134,7 @@ final class EPSGCodeFinder extends IdentifiedObjectFinder {
                 declaredType = pt;
                 setIgnoringAxes(previous);
             }
-            final Set<Number> filters = new LinkedHashSet<>(Containers.hashMapCapacity(find.size()));
+            final Set<Number> filters = JDK19.newLinkedHashSet(find.size());
             for (final IdentifiedObject dep : find) {
                 Identifier id = IdentifiedObjects.getIdentifier(dep, Citations.EPSG);
                 if (id != null) try {                                                   // Should never be null, but let be safe.
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/GridGroup.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/GridGroup.java
index c4d24e7717..4aef9ebfd5 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/GridGroup.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/GridGroup.java
@@ -18,7 +18,6 @@ package org.apache.sis.referencing.operation.gridded;
 
 import java.util.Map;
 import java.util.List;
-import java.util.LinkedHashMap;
 import java.io.IOException;
 import java.awt.Dimension;
 import java.awt.Rectangle;
@@ -33,7 +32,7 @@ import org.apache.sis.referencing.util.j2d.TileOrganizer;
 import org.apache.sis.referencing.util.j2d.Tile;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.util.internal.CollectionsExt;
-import org.apache.sis.util.collection.Containers;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -159,7 +158,7 @@ public final class GridGroup<C extends Quantity<C>, T extends Quantity<T>> exten
             throws IOException, FactoryException, NoninvertibleTransformException
     {
         final TileOrganizer mosaic = new TileOrganizer(null);
-        final Map<Tile,LoadedGrid<C,T>> grids = new LinkedHashMap<>(Containers.hashMapCapacity(subgrids.size()));
+        final Map<Tile,LoadedGrid<C,T>> grids = JDK19.newLinkedHashMap(subgrids.size());
         for (final LoadedGrid<C,T> grid : subgrids) {
             final int[] size = grid.getGridSize();
             final Tile  tile = new Tile(new Rectangle(size[0], size[1]),
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/LoadedGrid.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/LoadedGrid.java
index f6551d47ab..a7d139c534 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/LoadedGrid.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/LoadedGrid.java
@@ -19,7 +19,6 @@ package org.apache.sis.referencing.operation.gridded;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.AbstractMap;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.concurrent.Callable;
@@ -44,7 +43,6 @@ import org.apache.sis.util.collection.Cache;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.collection.DefaultTreeTable;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.datum.DatumShiftGrid;
@@ -53,6 +51,7 @@ import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.transform.InterpolatedTransform;
 import org.apache.sis.referencing.util.j2d.AffineTransform2D;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -495,7 +494,7 @@ public abstract class LoadedGrid<C extends Quantity<C>, T extends Quantity<T>> e
         if (subgrids == null) {
             return global;
         }
-        final Map<Envelope,MathTransform> specializations = new LinkedHashMap<>(Containers.hashMapCapacity(subgrids.length));
+        final Map<Envelope,MathTransform> specializations = JDK19.newLinkedHashMap(subgrids.length);
         for (final LoadedGrid<Angle,Angle> sg : subgrids) try {
             final Envelope domain = sg.getDomainOfValidity(Units.DEGREE);
             final MathTransform st = createGeodeticTransformation(provider, factory, sg);
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/NTv2.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/NTv2.java
index 0bde964b5e..f91ab9e1d6 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/NTv2.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/NTv2.java
@@ -52,11 +52,11 @@ import org.apache.sis.referencing.util.Formulas;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.parameter.Parameters;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.internal.Strings;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Messages;
 import org.apache.sis.measure.Units;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -441,7 +441,7 @@ public final class NTv2 extends AbstractProvider {
          * sub-grids (if any) as children.
          */
         final LoadedGrid<Angle,Angle> readAllGrids() throws IOException, FactoryException, NoninvertibleTransformException {
-            final Map<String,      LoadedGrid<Angle,Angle>>  grids    = new HashMap<>(Containers.hashMapCapacity(numGrids));
+            final Map<String,      LoadedGrid<Angle,Angle>>  grids    = JDK19.newHashMap(numGrids);
             final Map<String, List<LoadedGrid<Angle,Angle>>> children = new LinkedHashMap<>();   // Should have few entries.
             while (grids.size() < numGrids) {
                 readGrid(grids, children);
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_GeneralOperationParameter.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_GeneralOperationParameter.java
index 83eb702dc2..716af63e88 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_GeneralOperationParameter.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_GeneralOperationParameter.java
@@ -20,7 +20,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import jakarta.xml.bind.annotation.XmlElementRef;
@@ -39,13 +38,13 @@ import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.GeodeticException;
 import org.apache.sis.util.CorruptedObjectException;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.internal.CollectionsExt;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.xml.IdentifiedObject;
 import org.apache.sis.xml.IdentifierSpace;
 import org.apache.sis.xml.bind.Context;
 import org.apache.sis.xml.bind.gco.PropertyType;
-import org.apache.sis.util.resources.Errors;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -321,7 +320,7 @@ public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralO
                                           boolean                            canSubstitute)
     {
         boolean isCompatible = true;
-        final Set<GeneralParameterDescriptor> included = new HashSet<>(Containers.hashMapCapacity(provided.length));
+        final Set<GeneralParameterDescriptor> included = JDK19.newHashSet(provided.length);
         for (int i=0; i<provided.length; i++) {
             final GeneralParameterDescriptor p = provided[i];
             try {
@@ -419,7 +418,7 @@ public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralO
             if (size == 0) {
                 return false;
             }
-            final Set<NamedIdentifier> c = new HashSet<>(Containers.hashMapCapacity(size));
+            final Set<NamedIdentifier> c = JDK19.newHashSet(size);
             for (final T e : complete) {
                 c.add(toNamedIdentifier(e));
             }
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_OperationParameterGroup.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_OperationParameterGroup.java
index b31e5daec4..9f49da2a46 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_OperationParameterGroup.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_OperationParameterGroup.java
@@ -18,7 +18,6 @@ package org.apache.sis.xml.bind.referencing;
 
 import java.util.Map;
 import java.util.List;
-import java.util.LinkedHashMap;
 import jakarta.xml.bind.annotation.XmlElement;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
@@ -27,7 +26,7 @@ import org.apache.sis.xml.bind.gco.PropertyType;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.util.CorruptedObjectException;
-import org.apache.sis.util.collection.Containers;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -141,8 +140,7 @@ public final class CC_OperationParameterGroup extends PropertyType<CC_OperationP
         if (descriptors.isEmpty()) {
             return fromValues;
         }
-        final Map<String,GeneralParameterDescriptor> union =
-                new LinkedHashMap<>(Containers.hashMapCapacity(descriptors.size()));
+        final Map<String,GeneralParameterDescriptor> union = JDK19.newLinkedHashMap(descriptors.size());
         /*
          * Collect the descriptors declared explicitly in the ParameterDescriptorGroup. We should never have
          * two descriptors of the same name since the DefaultParameterDescriptorGroup constructor checked for
diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Variable.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Variable.java
index ccee1ed7a4..acfaa1c0ad 100644
--- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Variable.java
+++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Variable.java
@@ -42,12 +42,12 @@ import org.apache.sis.math.MathFunctions;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.util.ArraysExt;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.collection.WeakHashSet;
 import org.apache.sis.util.internal.Numerics;
 import org.apache.sis.util.internal.CollectionsExt;
 import org.apache.sis.util.internal.UnmodifiableArrayList;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.pending.jdk.JDK19;
 import static org.apache.sis.storage.base.StoreUtilities.ALLOW_LAST_RESORT_STATISTICS;
 
 
@@ -241,7 +241,7 @@ public abstract class Variable extends Node {
              */
             Exception     error    = null;
             StringBuilder invalids = null;
-            enumeration = new HashMap<>(Containers.hashMapCapacity(count));
+            enumeration = JDK19.newHashMap(count);
             for (int i=0; i<count; i++) try {
                 final CharSequence label = labels[i];
                 if (label != null) {
diff --git a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
index 14d5d822c5..6663a4d973 100644
--- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
+++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
@@ -52,20 +52,20 @@ import org.apache.sis.storage.netcdf.base.Variable;
 import org.apache.sis.storage.netcdf.base.Dimension;
 import org.apache.sis.storage.netcdf.base.Convention;
 import org.apache.sis.storage.netcdf.base.NamedElement;
+import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.io.stream.ChannelDataInput;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.internal.Constants;
 import org.apache.sis.util.internal.CollectionsExt;
 import org.apache.sis.util.internal.StandardDateFormat;
-import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.measure.Units;
 import org.apache.sis.math.Vector;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -658,7 +658,7 @@ public final class ChannelDecoder extends Decoder {
         if (attributes.size() >= attributeMap.size()) {
             return Collections.unmodifiableSet(attributeMap.keySet());
         }
-        final Set<String> attributeNames = new LinkedHashSet<>(Containers.hashMapCapacity(attributes.size()));
+        final Set<String> attributeNames = JDK19.newLinkedHashSet(attributes.size());
         attributes.forEach((e) -> attributeNames.add(e.getKey()));
         return attributeNames;
     }
diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java
index 1da43c9cda..751aa2a14c 100644
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java
@@ -17,7 +17,6 @@
 package org.apache.sis.storage.sql.feature;
 
 import java.util.Map;
-import java.util.HashMap;
 import java.util.Optional;
 import java.util.stream.Stream;
 import java.sql.Connection;
@@ -31,9 +30,9 @@ import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.InternalDataStoreException;
 import org.apache.sis.metadata.sql.util.Reflection;
 import org.apache.sis.metadata.sql.util.SQLBuilder;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.collection.WeakValueHashMap;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.iso.DefaultNameSpace;
 
@@ -366,7 +365,7 @@ final class Table extends AbstractFeatureSet {
         synchronized (this) {
             m = attributeToColumns;
             if (m == null) {
-                m = new HashMap<>(Containers.hashMapCapacity(attributes.length));
+                m = JDK19.newHashMap(attributes.length);
                 for (final Column c : attributes) {
                     String label = c.propertyName;
                     m.put(label, c);
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
index 056eba2476..d4da656505 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
@@ -18,9 +18,7 @@ package org.apache.sis.storage;
 
 import java.util.Arrays;
 import java.util.Set;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.LinkedHashMap;
 import java.util.Objects;
 import java.util.OptionalLong;
 import java.util.function.Function;
@@ -41,10 +39,10 @@ import org.apache.sis.filter.Optimization;
 import org.apache.sis.filter.internal.SortByComparator;
 import org.apache.sis.filter.internal.XPath;
 import org.apache.sis.storage.internal.Resources;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.iso.Names;
 import org.apache.sis.util.resources.Vocabulary;
 
@@ -228,7 +226,7 @@ public class FeatureQuery extends Query implements Cloneable, Serializable {
         if (properties != null) {
             ArgumentChecks.ensureNonEmpty("properties", properties);
             properties = properties.clone();
-            final Map<Object,Integer> uniques = new LinkedHashMap<>(Containers.hashMapCapacity(properties.length));
+            final Map<Object,Integer> uniques = JDK19.newLinkedHashMap(properties.length);
             for (int i=0; i<properties.length; i++) {
                 final NamedExpression c = properties[i];
                 ArgumentChecks.ensureNonNullElement("properties", i, c);
@@ -755,7 +753,7 @@ public class FeatureQuery extends Query implements Cloneable, Serializable {
                  * We may have collision of their `String` representations however, which is okay.
                  */
                 if (names == null) {
-                    names = new HashSet<>(Containers.hashMapCapacity(projection.length));
+                    names = JDK19.newHashSet(projection.length);
                     for (final NamedExpression p : projection) {
                         if (p.alias != null) {
                             names.add(p.alias.toString());
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
index ef3cc182f2..8bdc7e6504 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
@@ -18,7 +18,6 @@ package org.apache.sis.storage.event;
 
 import java.util.Map;
 import java.util.Set;
-import java.util.HashSet;
 import java.util.Locale;
 import java.util.Optional;
 import java.util.IdentityHashMap;
@@ -35,14 +34,14 @@ import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Vocabulary;
-import org.apache.sis.util.collection.Containers;
+import org.apache.sis.util.internal.Strings;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.Resource;
 import org.apache.sis.storage.internal.Resources;
 import org.apache.sis.storage.base.StoreResource;
 import org.apache.sis.storage.base.StoreUtilities;
-import org.apache.sis.util.internal.Strings;
 
 
 /**
@@ -886,7 +885,7 @@ public class StoreListeners implements Localized {
     public synchronized void setUsableEventTypes(final Class<?>... permitted) {
         ArgumentChecks.ensureNonEmpty("permitted", permitted);
         final Set<Class<? extends StoreEvent>> current = permittedEventTypes;
-        final Set<Class<? extends StoreEvent>> types = new HashSet<>(Containers.hashMapCapacity(permitted.length));
+        final Set<Class<? extends StoreEvent>> types = JDK19.newHashSet(permitted.length);
         for (final Class<?> type : permitted) {
             if (current != null ? current.contains(type) : StoreEvent.class.isAssignableFrom(type)) {
                 types.add((Class<? extends StoreEvent>) type);
diff --git a/endorsed/src/org.apache.sis.util/main/module-info.java b/endorsed/src/org.apache.sis.util/main/module-info.java
index 1862fabe6b..4f9e559113 100644
--- a/endorsed/src/org.apache.sis.util/main/module-info.java
+++ b/endorsed/src/org.apache.sis.util/main/module-info.java
@@ -165,6 +165,7 @@ module org.apache.sis.util {
             org.apache.sis.referencing.database;        // In the "non-free" sub-project.
 
     exports org.apache.sis.pending.jdk to
+            org.apache.sis.metadata,
             org.apache.sis.referencing,
             org.apache.sis.referencing.gazetteer,
             org.apache.sis.feature,
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK19.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK19.java
index 933e9ef92e..12c8f7ba76 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK19.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK19.java
@@ -16,6 +16,12 @@
  */
 package org.apache.sis.pending.jdk;
 
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedHashMap;
+import static org.apache.sis.util.collection.Containers.hashMapCapacity;
+
 
 /**
  * Place holder for some functionalities defined in a JDK more recent than Java 11.
@@ -38,4 +44,20 @@ public final class JDK19 {
      */
     private JDK19() {
     }
+
+    public static <T> HashSet<T> newHashSet(int n) {
+        return new HashSet<>(hashMapCapacity(n));
+    }
+
+    public static <K,V> HashMap<K,V> newHashMap(int n) {
+        return new HashMap<>(hashMapCapacity(n));
+    }
+
+    public static <T> LinkedHashSet<T> newLinkedHashSet(int n) {
+        return new LinkedHashSet<>(hashMapCapacity(n));
+    }
+
+    public static <K, V> LinkedHashMap<K,V> newLinkedHashMap(int n) {
+        return new LinkedHashMap<>(hashMapCapacity(n));
+    }
 }
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java
index cf86f7836b..194d0938b6 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java
@@ -33,7 +33,7 @@ import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Modifier;
 import org.opengis.annotation.UML;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -466,7 +466,7 @@ public final class Classes extends Static {
         final Class<?>[] interfaces = type.getInterfaces();
         for (int i=0; i<interfaces.length; i++) {
             if (addTo == null) {
-                addTo = new LinkedHashSet<>(hashMapCapacity(interfaces.length));
+                addTo = JDK19.newLinkedHashSet(interfaces.length);
             }
             if (!addTo.add(interfaces[i])) {
                 interfaces[i] = null;           // Remember that this interface is already present.
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Locales.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Locales.java
index f72c51f242..274640eb78 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Locales.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Locales.java
@@ -21,15 +21,13 @@ import java.util.Set;
 import java.util.Arrays;
 import java.util.Locale;
 import java.util.TreeMap;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
 import java.util.MissingResourceException;
 import java.util.IllformedLocaleException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import org.apache.sis.pending.jdk.JDK19;
 import org.apache.sis.util.logging.Logging;
 import static org.apache.sis.util.CharSequences.trimWhitespaces;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
 import static org.apache.sis.util.resources.IndexedResourceBundle.LOGGER;
 
 
@@ -57,7 +55,7 @@ public final class Locales extends Static {
     private static final Map<Locale,Locale> POOL;
     static {
         final Locale[] locales = Locale.getAvailableLocales();
-        POOL = new HashMap<>(hashMapCapacity(locales.length));
+        POOL = JDK19.newHashMap(locales.length);
         for (final Locale lc : locales) {
             POOL.put(lc, lc);
         }
@@ -211,7 +209,7 @@ filter: for (final Locale locale : locales) {
      */
     @SuppressWarnings("deprecation")
     private static Locale[] getLanguages(final Locale... locales) {
-        final Set<String> codes = new LinkedHashSet<>(hashMapCapacity(locales.length));
+        final Set<String> codes = JDK19.newLinkedHashSet(locales.length);
         for (final Locale locale : locales) {
             codes.add(locale.getLanguage());
         }
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java
index 72404c405a..d2e90b086c 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Containers.java
@@ -251,26 +251,24 @@ public final class Containers extends Static {
     }
 
     /**
-     * Returns the capacity to be given to the {@link java.util.HashMap#HashMap(int) HashMap}
-     * constructor for holding the given number of elements. This method computes the capacity
-     * for the default <cite>load factor</cite>, which is 0.75.
+     * Returns the capacity to give to the {@code HashMap} and {@code HashSet} constructors for holding the
+     * given number of elements. This method computes the capacity for the default load factor, which is 0.75.
+     * This capacity is applicable to the following classes:
+     * {@link java.util.HashSet},
+     * {@link java.util.HashMap},
+     * {@link java.util.LinkedHashSet} and
+     * {@link java.util.LinkedHashMap}.
+     * This capacity is <strong>not</strong> applicable to {@link java.util.IdentityHashMap}.
      *
-     * <p>The same calculation can be used for {@link java.util.LinkedHashMap} and
-     * {@link java.util.HashSet} as well, which are built on top of {@code HashMap}.
-     * However, it is not needed for {@link java.util.IdentityHashMap}.</p>
-     *
-     * <h4>Future evolution</h4>
-     * This method may be deprecated in favor of {@code HashMap.newHashMap(int)}
-     * when Apache SIS will be allowed to compile for JDK19.
+     * <p>Since Java 19, the static factory methods in above-cited classes should be used instead of this method.
+     * However, this {@code hashMapCapacity} method is still useful in a few cases where the standard factory methods
+     * cannot be invoked, for example because the collection to construct is a subclasses for the standard classes.</p>
      *
      * @param  count  the number of elements to be put into the hash map or hash set.
      * @return the minimal initial capacity to be given to the hash map constructor.
      */
     public static int hashMapCapacity(final int count) {
-        /*
-         * Dividing 'count' by 0.75 is equivalent to multiplying by 1.333333…
-         * rounded to next integer.
-         */
+        // Dividing `count` by 0.75 is equivalent to multiplying by 1.333333… rounded to next integer.
         return (count * 4 + 2) / 3;
     }
 
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java
index c5b9e07b59..a8387c81ce 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/DefaultTreeTable.java
@@ -28,8 +28,8 @@ import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.internal.Cloner;
 import org.apache.sis.util.internal.Acyclic;
 import org.apache.sis.util.internal.UnmodifiableArrayList;
+import org.apache.sis.pending.jdk.JDK19;
 import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
 
 
 /**
@@ -153,8 +153,8 @@ public class DefaultTreeTable implements TreeTable, Cloneable, Serializable {
         Map<TableColumn<?>,Integer> map;
         switch (columns.length) {
             case 0:  map = Map.of(); break;
-            case 1:  map = null; break; // Will be created inside the loop (common case).
-            default: map = new LinkedHashMap<>(hashMapCapacity(columns.length)); break;
+            case 1:  map = null; break;         // Will be created inside the loop (common case).
+            default: map = JDK19.newLinkedHashMap(columns.length); break;
         }
         for (int i=0; i<columns.length; i++) {
             final TableColumn<?> column = columns[i];
diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/CollectionsExt.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/CollectionsExt.java
index 57ff37a327..5cbe4bfd8d 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/CollectionsExt.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/CollectionsExt.java
@@ -25,7 +25,7 @@ import org.apache.sis.util.Numbers;
 import org.apache.sis.util.collection.CodeListSet;
 import org.apache.sis.util.collection.CheckedContainer;
 import org.apache.sis.util.resources.Errors;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
+import org.apache.sis.pending.jdk.JDK19;
 
 
 /**
@@ -317,7 +317,7 @@ public final class CollectionsExt extends Static {
         if (Enum.class.isAssignableFrom(type)) {
             return EnumSet.noneOf((Class) type);
         }
-        return new LinkedHashSet<>(hashMapCapacity(count));
+        return JDK19.newLinkedHashSet(count);
     }
 
     /**
@@ -826,7 +826,7 @@ public final class CollectionsExt extends Static {
         if (entries == null || entries.isEmpty()) {
             return Collections.emptyMap();
         }
-        final Map<String,E> map = new LinkedHashMap<>(hashMapCapacity(entries.size()));
+        final Map<String,E> map = JDK19.newLinkedHashMap(entries.size());
         final Set<String> generated = new HashSet<>();
         for (final Map.Entry<String, ? extends E> entry : entries) {
             final String name = entry.getKey();
diff --git a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestRunner.java b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestRunner.java
index b6010515a5..9c4e92b59d 100644
--- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestRunner.java
+++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestRunner.java
@@ -23,8 +23,8 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.io.PrintWriter;
 import org.apache.sis.util.ArraysExt;
+import org.apache.sis.pending.jdk.JDK19;
 import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
 
 // Test dependencies
 import org.junit.Test;
@@ -178,7 +178,7 @@ public final class TestRunner extends BlockJUnit4ClassRunner {
         final TestClass testClass = getTestClass();
         final List<FrameworkMethod> depends = testClass.getAnnotatedMethods(DependsOnMethod.class);
         if (!isNullOrEmpty(depends)) {
-            final Set<String> dependencies = new HashSet<>(hashMapCapacity(depends.size()));
+            final Set<String> dependencies = JDK19.newHashSet(depends.size());
             for (final FrameworkMethod method : depends) {
                 for (final String value : method.getAnnotation(DependsOnMethod.class).value()) {
                     dependencies.add(value);