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

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new b98942fba Add ArrayUtils.getDimensions(Object)
b98942fba is described below

commit b98942fba3b2b4ba90c43bfa4effb48a170fe1a6
Author: Gary Gregory <[email protected]>
AuthorDate: Sat Jan 24 08:25:54 2026 -0500

    Add ArrayUtils.getDimensions(Object)
---
 src/changes/changes.xml                            |   1 +
 .../java/org/apache/commons/lang3/ArrayUtils.java  |  23 +++
 .../commons/lang3/ArrayUtilsGetDimensions.java     | 157 +++++++++++++++++++++
 3 files changed, 181 insertions(+)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d8d348187..7408ebd83 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -114,6 +114,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">JavaVersion.get(String) now support Java 26 and 27.</action>
     <action issue="LANG-1810" type="add" dev="ggregory" due-to="Yelim Koo, 
Gary Gregory">Deprecate ArrayUtils.SOFT_MAX_ARRAY_LENGTH in favor of 
SAFE_MAX_ARRAY_LENGTH #1559.</action>
     <action                   type="add" dev="ggregory" due-to="Gary Gregory, 
Theodora Anastasia Lazaridou">Add long support to BitField #1561.</action>
+    <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add ArrayUtils.getDimensions(Object).</action>
     <!-- UPDATE -->
     <action                   type="update" dev="ggregory" due-to="Gary 
Gregory, Dependabot">Bump org.apache.commons:commons-parent from 92 to 96 
#1498.</action>
     <action                   type="update" dev="ggregory" due-to="Gary 
Gregory">[test] Bump org.apache.commons:commons-text from 1.14.0 to 
1.15.0.</action>
diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java 
b/src/main/java/org/apache/commons/lang3/ArrayUtils.java
index d2e57b221..b4703bd2b 100644
--- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java
+++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java
@@ -1849,6 +1849,29 @@ public static <T> Class<T> getComponentType(final T[] 
array) {
         return ClassUtils.getComponentType(ObjectUtils.getClass(array));
     }
 
+    /**
+     * Gets the number of dimensions of an array.
+     * <p>
+     * The <a 
href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3";>JVM
 specification</a> limits the number of dimensions to 255.
+     * </p>
+     *
+     * @param array the array, may be {@code null}.
+     * @return The number of dimensions, 0 if the input is null or not an 
array. The JVM specification limits the number of dimensions to 255.
+     * @since 3.21.0
+     * @see <a 
href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3";>JVM
 specification Field Descriptors</a>
+     */
+    public static int getDimensions(final Object array) {
+        int dimensions = 0;
+        if (array != null) {
+            Class<?> arrayClass = array.getClass();
+            while (arrayClass.isArray()) {
+                dimensions++;
+                arrayClass = arrayClass.getComponentType();
+            }
+        }
+        return dimensions;
+    }
+
     /**
      * Gets the length of the specified array.
      * This method can deal with {@link Object} arrays and with primitive 
arrays.
diff --git 
a/src/test/java/org/apache/commons/lang3/ArrayUtilsGetDimensions.java 
b/src/test/java/org/apache/commons/lang3/ArrayUtilsGetDimensions.java
new file mode 100644
index 000000000..10e1e6cac
--- /dev/null
+++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsGetDimensions.java
@@ -0,0 +1,157 @@
+/*
+ * 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
+ *
+ *      https://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.commons.lang3;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class ArrayUtilsGetDimensions {
+
+    // Tests cyclic references
+    static class Node {
+
+        String name;
+
+        Node next;
+
+        Node(final String name) {
+            this.name = name;
+        }
+    }
+
+    private static Stream<Arguments> provideArraysWithExpectedDimensions() {
+        return Stream.of(Arguments.of(new int[] { 1, 2, 3 }, 1), 
Arguments.of(new int[][] { { 1, 2 }, { 3, 4 } }, 2),
+                Arguments.of(new int[][][] { { { 1 } } }, 3), Arguments.of(new 
String[] { "a", "b" }, 1), Arguments.of(new String[][] { { "a" }, { "b" } }, 2),
+                Arguments.of(new Object[5], 1), Arguments.of(new 
boolean[2][3], 2), Arguments.of(new char[1][2][3][4], 4));
+    }
+
+    @Test
+    void testArraysOfArrays() {
+        final Object[] arrayOfArrays = { new int[] { 1, 2 }, new String[] { 
"a", "b" } };
+        assertEquals(1, ArrayUtils.getDimensions(arrayOfArrays));
+    }
+
+    @Test
+    void testArraysWithCyclicObjects() {
+        final Node node1 = new Node("A");
+        final Node node2 = new Node("B");
+        node1.next = node2;
+        node2.next = node1; // Create cycle
+        final Node[] arr = { node1, node2 };
+        assertEquals(1, ArrayUtils.getDimensions(arr));
+        final Node[][] arr2D = { { node1, node2 }, { node2, node1 } };
+        assertEquals(2, ArrayUtils.getDimensions(arr2D));
+    }
+
+    @Test
+    void testArraysWithNullElements() {
+        final String[] arrWithNull = { null, "test", null };
+        assertEquals(1, ArrayUtils.getDimensions(arrWithNull));
+        final String[][] arr2DWithNull = { { null, "a" }, null, { "b" } };
+        assertEquals(2, ArrayUtils.getDimensions(arr2DWithNull));
+    }
+
+    @Test
+    void testEmptyOneDimensionalArrays() {
+        assertEquals(1, ArrayUtils.getDimensions(new int[0]));
+        assertEquals(1, ArrayUtils.getDimensions(new String[0]));
+    }
+
+    @Test
+    void testHighDimensionalArrays() {
+        assertEquals(4, ArrayUtils.getDimensions(new int[1][2][3][4]));
+        assertEquals(5, ArrayUtils.getDimensions(new byte[1][1][1][1][1]));
+        assertEquals(6, ArrayUtils.getDimensions(new 
String[2][2][2][2][2][2]));
+    }
+
+    @Test
+    void testInitializedArrays() {
+        final int[] arr1D = { 1, 2, 3, 4, 5 };
+        assertEquals(1, ArrayUtils.getDimensions(arr1D));
+        final int[][] arr2D = { { 1, 2, 3 }, { 4, 5, 6 } };
+        assertEquals(2, ArrayUtils.getDimensions(arr2D));
+        final int[][][] arr3D = { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } 
} };
+        assertEquals(3, ArrayUtils.getDimensions(arr3D));
+    }
+
+    @Test
+    void testJaggedArrays() {
+        final int[][] jagged = { { 1, 2 }, { 3, 4, 5 }, { 6 } };
+        assertEquals(2, ArrayUtils.getDimensions(jagged));
+        final String[][] jaggedStrings = { { "a" }, { "b", "c", "d" } };
+        assertEquals(2, ArrayUtils.getDimensions(jaggedStrings));
+    }
+
+    @Test
+    void testNonArrayObject() {
+        assertEquals(0, ArrayUtils.getDimensions("Not an array"));
+        assertEquals(0, ArrayUtils.getDimensions(42));
+        assertEquals(0, ArrayUtils.getDimensions(new Object()));
+        assertEquals(0, ArrayUtils.getDimensions(3.14));
+    }
+
+    @Test
+    void testNullArray() {
+        assertEquals(0, ArrayUtils.getDimensions(null));
+    }
+
+    @Test
+    void testOneDimensionalObjectArrays() {
+        assertEquals(1, ArrayUtils.getDimensions(new String[5]));
+        assertEquals(1, ArrayUtils.getDimensions(new Object[10]));
+        assertEquals(1, ArrayUtils.getDimensions(new Integer[3]));
+    }
+
+    @Test
+    void testOneDimensionalPrimitiveArrays() {
+        assertEquals(1, ArrayUtils.getDimensions(new int[5]));
+        assertEquals(1, ArrayUtils.getDimensions(new byte[10]));
+        assertEquals(1, ArrayUtils.getDimensions(new short[3]));
+        assertEquals(1, ArrayUtils.getDimensions(new long[7]));
+        assertEquals(1, ArrayUtils.getDimensions(new float[4]));
+        assertEquals(1, ArrayUtils.getDimensions(new double[6]));
+        assertEquals(1, ArrayUtils.getDimensions(new boolean[2]));
+        assertEquals(1, ArrayUtils.getDimensions(new char[8]));
+    }
+
+    @Test
+    void testThreeDimensionalArrays() {
+        assertEquals(3, ArrayUtils.getDimensions(new int[2][3][4]));
+        assertEquals(3, ArrayUtils.getDimensions(new String[1][2][3]));
+        assertEquals(3, ArrayUtils.getDimensions(new Object[5][5][5]));
+    }
+
+    @Test
+    void testTwoDimensionalArrays() {
+        assertEquals(2, ArrayUtils.getDimensions(new int[3][4]));
+        assertEquals(2, ArrayUtils.getDimensions(new String[2][5]));
+        assertEquals(2, ArrayUtils.getDimensions(new double[1][1]));
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideArraysWithExpectedDimensions")
+    void testVariousArrayTypes(final Object array, final int 
expectedDimensions) {
+        assertEquals(expectedDimensions, ArrayUtils.getDimensions(array));
+    }
+}

Reply via email to