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));
+ }
+}