diff --git a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java index 316a8e2d7fc..28c490336a2 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -58,6 +58,9 @@ public abstract class ObjectUtils { private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END; private static final String ARRAY_ELEMENT_SEPARATOR = ", "; private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; + private static final String NON_EMPTY_ARRAY = ARRAY_START + "..." + ARRAY_END; + private static final String EMPTY_COLLECTION = "[]"; + private static final String NON_EMPTY_COLLECTION = "[...]"; /** @@ -936,6 +939,16 @@ public abstract class ObjectUtils { return (optional.isEmpty() ? "Optional.empty" : "Optional[%s]".formatted(nullSafeConciseToString(optional.get()))); } + if (obj.getClass().isArray()) { + return (Array.getLength(obj) == 0 ? EMPTY_ARRAY : NON_EMPTY_ARRAY); + } + if (obj instanceof Collection collection) { + return (collection.isEmpty() ? EMPTY_COLLECTION : NON_EMPTY_COLLECTION); + } + if (obj instanceof Map map) { + // EMPTY_ARRAY and NON_EMPTY_ARRAY are also used for maps. + return (map.isEmpty() ? EMPTY_ARRAY : NON_EMPTY_ARRAY); + } if (obj instanceof Class clazz) { return clazz.getName(); } diff --git a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java index 1bbd0f9e92d..3529138fc4a 100644 --- a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java @@ -30,7 +30,6 @@ import java.nio.file.Path; import java.sql.SQLException; import java.time.LocalDate; import java.time.ZoneId; -import java.util.ArrayList; import java.util.Collections; import java.util.Currency; import java.util.Date; @@ -1034,19 +1033,47 @@ class ObjectUtilsTests { } @Test - void nullSafeConciseToStringForArraysAndCollections() { - List list = List.of("a", "b", "c"); - assertThat(ObjectUtils.nullSafeConciseToString(new int[][] {{1, 2}, {3, 4}})).startsWith(prefix(int[][].class)); - assertThat(ObjectUtils.nullSafeConciseToString(list.toArray())).startsWith(prefix(Object[].class)); - assertThat(ObjectUtils.nullSafeConciseToString(list.toArray(String[]::new))).startsWith(prefix(String[].class)); - assertThat(ObjectUtils.nullSafeConciseToString(new ArrayList<>(list))).startsWith(prefix(ArrayList.class)); - assertThat(ObjectUtils.nullSafeConciseToString(new HashSet<>(list))).startsWith(prefix(HashSet.class)); + void nullSafeConciseToStringForEmptyArrays() { + assertThat(ObjectUtils.nullSafeConciseToString(new char[] {})).isEqualTo("{}"); + assertThat(ObjectUtils.nullSafeConciseToString(new int[][] {})).isEqualTo("{}"); + assertThat(ObjectUtils.nullSafeConciseToString(new String[] {})).isEqualTo("{}"); + assertThat(ObjectUtils.nullSafeConciseToString(new Integer[][] {})).isEqualTo("{}"); } @Test - void nullSafeConciseToStringForMaps() { + void nullSafeConciseToStringForNonEmptyArrays() { + assertThat(ObjectUtils.nullSafeConciseToString(new char[] {'a'})).isEqualTo("{...}"); + assertThat(ObjectUtils.nullSafeConciseToString(new int[][] {{1}, {2}})).isEqualTo("{...}"); + assertThat(ObjectUtils.nullSafeConciseToString(new String[] {"enigma"})).isEqualTo("{...}"); + assertThat(ObjectUtils.nullSafeConciseToString(new Integer[][] {{1}, {2}})).isEqualTo("{...}"); + } + + @Test + void nullSafeConciseToStringForEmptyCollections() { + List list = List.of(); + Set set = Set.of(); + assertThat(ObjectUtils.nullSafeConciseToString(list)).isEqualTo("[]"); + assertThat(ObjectUtils.nullSafeConciseToString(set)).isEqualTo("[]"); + } + + @Test + void nullSafeConciseToStringForNonEmptyCollections() { + List list = List.of("a", "b"); + Set set = Set.of(1); + assertThat(ObjectUtils.nullSafeConciseToString(list)).isEqualTo("[...]"); + assertThat(ObjectUtils.nullSafeConciseToString(set)).isEqualTo("[...]"); + } + + @Test + void nullSafeConciseToStringForEmptyMaps() { + Map map = new HashMap(); + assertThat(ObjectUtils.nullSafeConciseToString(map)).isEqualTo("{}"); + } + + @Test + void nullSafeConciseToStringForNonEmptyMaps() { Map map = Map.of("a", 1, "b", 2, "c", 3); - assertThat(ObjectUtils.nullSafeConciseToString(map)).startsWith(prefix(map.getClass())); + assertThat(ObjectUtils.nullSafeConciseToString(map)).isEqualTo("{...}"); } @Test