diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 937e296eb2b..8850d9cf06d 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -18,18 +18,24 @@ package org.springframework.util; import java.io.Closeable; import java.io.Externalizable; +import java.io.File; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; +import java.net.InetAddress; import java.net.URI; import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.time.ZoneId; import java.time.temporal.Temporal; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Currency; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; @@ -43,7 +49,9 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.StringJoiner; +import java.util.TimeZone; import java.util.UUID; +import java.util.regex.Pattern; import org.springframework.lang.Nullable; @@ -538,10 +546,12 @@ public abstract class ClassUtils { * Delegate for {@link org.springframework.beans.BeanUtils#isSimpleValueType}. * Also used by {@link ObjectUtils#nullSafeConciseToString}. *
Check if the given type represents a common "simple" value type: - * a primitive or primitive wrapper, an {@code Enum}, a {@code String} - * or other {@code CharSequence}, a {@code Number}, a {@code Date}, - * a {@code Temporal}, a {@code UUID}, a {@code URI}, a {@code URL}, - * a {@code Locale}, or a {@code Class}. + * a primitive or primitive wrapper, an {@link Enum}, a {@link String} + * or other {@link CharSequence}, a {@link Number}, a {@link Date}, + * a {@link Temporal}, a {@link ZoneId} a {@link TimeZone}, a {@link File}, + * a {@link Path}, a {@link URI}, a {@link URL}, an {@link InetAddress}, + * a {@link Charset}, a {@link Currency}, a {@link Locale}, a {@link UUID}, + * a {@link Pattern}, or a {@link Class}. *
{@code Void} and {@code void} are not considered simple value types. * @param type the type to check * @return whether the given type represents a "simple" value type, @@ -556,10 +566,18 @@ public abstract class ClassUtils { Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || Temporal.class.isAssignableFrom(type) || - UUID.class == type || + ZoneId.class.isAssignableFrom(type) || + TimeZone.class.isAssignableFrom(type) || + File.class.isAssignableFrom(type) || + Path.class.isAssignableFrom(type) || + Charset.class.isAssignableFrom(type) || + Currency.class.isAssignableFrom(type) || + InetAddress.class.isAssignableFrom(type) || URI.class == type || URL.class == type || + UUID.class == type || Locale.class == type || + Pattern.class == type || Class.class == type)); } 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 d7a9b2a008c..316a8e2d7fc 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -17,11 +17,14 @@ package org.springframework.util; import java.lang.reflect.Array; +import java.nio.charset.Charset; +import java.time.ZoneId; import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Optional; import java.util.StringJoiner; +import java.util.TimeZone; import org.springframework.lang.Nullable; @@ -894,19 +897,30 @@ public abstract class ObjectUtils { *
Returns: *
In the context of this method, a simple value type is any of the following:
- * a primitive wrapper (excluding {@code Void}), an {@code Enum}, a {@code Number},
- * a {@code Date}, a {@code Temporal}, a {@code UUID}, a {@code URI}, a {@code URL},
- * or a {@code Locale}.
+ * primitive wrapper (excluding {@link Void}), {@link Enum}, {@link Number},
+ * {@link java.util.Date Date}, {@link java.time.temporal.Temporal Temporal},
+ * {@link java.io.File File}, {@link java.nio.file.Path Path},
+ * {@link java.net.URI URI}, {@link java.net.URL URL},
+ * {@link java.net.InetAddress InetAddress}, {@link java.util.Currency Currency},
+ * {@link java.util.Locale Locale}, {@link java.util.UUID UUID},
+ * {@link java.util.regex.Pattern Pattern}.
* @param obj the object to build a string representation for
* @return a concise string representation of the supplied object
* @since 5.3.27
@@ -918,9 +932,22 @@ public abstract class ObjectUtils {
if (obj == null) {
return "null";
}
+ if (obj instanceof Optional> optional) {
+ return (optional.isEmpty() ? "Optional.empty" :
+ "Optional[%s]".formatted(nullSafeConciseToString(optional.get())));
+ }
if (obj instanceof Class> clazz) {
return clazz.getName();
}
+ if (obj instanceof Charset charset) {
+ return charset.name();
+ }
+ if (obj instanceof TimeZone timeZone) {
+ return timeZone.getID();
+ }
+ if (obj instanceof ZoneId zoneId) {
+ return zoneId.getId();
+ }
if (obj instanceof CharSequence charSequence) {
return StringUtils.truncate(charSequence);
}
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 3ec2373bb80..025c3a99f5c 100644
--- a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java
+++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java
@@ -16,20 +16,34 @@
package org.springframework.util;
+import java.io.File;
import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
+import java.net.UnknownHostException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+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;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.TimeZone;
import java.util.UUID;
+import java.util.regex.Pattern;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -232,7 +246,7 @@ class ObjectUtilsTests {
}
@Test
- void addObjectToNullArray() throws Exception {
+ void addObjectToNullArray() {
String newElement = "foo";
String[] newArray = ObjectUtils.addObjectToArray(null, newElement);
assertThat(newArray).hasSize(1);
@@ -240,14 +254,14 @@ class ObjectUtilsTests {
}
@Test
- void addNullObjectToNullArray() throws Exception {
+ void addNullObjectToNullArray() {
Object[] newArray = ObjectUtils.addObjectToArray(null, null);
assertThat(newArray).hasSize(1);
assertThat(newArray[0]).isNull();
}
@Test
- void nullSafeEqualsWithArrays() throws Exception {
+ void nullSafeEqualsWithArrays() {
assertThat(ObjectUtils.nullSafeEquals(new String[] {"a", "b", "c"}, new String[] {"a", "b", "c"})).isTrue();
assertThat(ObjectUtils.nullSafeEquals(new int[] {1, 2, 3}, new int[] {1, 2, 3})).isTrue();
}
@@ -823,6 +837,41 @@ class ObjectUtilsTests {
assertThat(ObjectUtils.nullSafeConciseToString(null)).isEqualTo("null");
}
+ @Test
+ void nullSafeConciseToStringForEmptyOptional() {
+ Optional