From 01f717375be65d82df61441c8dced6ca6189eca7 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 25 Aug 2023 15:20:24 +0200 Subject: [PATCH] Introduce ObjectUtils#nullSafeHash(Object... element) This commit deprecates the various nullSafeHashCode methods taking array types as they are superseded by Arrays.hashCode now. This means that the now only remaining nullSafeHashCode method does not trigger a warning only if the target type is not an array. At the same time, there are multiple use of this method on several elements, handling the accumulation of hash codes. For that reason, this commit also introduces a nullSafeHash that takes an array of elements. The only difference between Objects.hash is that this method handles arrays. The codebase has been reviewed to use any of those two methods when it is possible. Closes gh-29051 --- .../aspectj/AspectJExpressionPointcut.java | 7 +- .../aop/aspectj/TypePatternClassFilter.java | 4 +- .../aop/support/ClassFilters.java | 4 +- .../AbstractBeanFactoryBasedTargetSource.java | 3 +- .../aop/target/EmptyTargetSource.java | 3 +- .../cache/config/TestEntity.java | 4 +- .../beans/BeanMetadataAttribute.java | 2 +- .../beans/ExtendedBeanInfo.java | 10 +- .../GenericTypeAwarePropertyDescriptor.java | 7 +- .../springframework/beans/PropertyValue.java | 2 +- .../beans/factory/InjectionPoint.java | 5 +- .../factory/config/BeanDefinitionHolder.java | 6 +- .../config/ConstructorArgumentValues.java | 2 +- .../factory/config/TypedStringValue.java | 2 +- .../beans/factory/support/MethodOverride.java | 4 +- .../mail/SimpleMailMessage.java | 10 +- .../AbstractApplicationEventMulticaster.java | 3 +- .../support/ApplicationListenerDetector.java | 4 +- .../DefaultMessageSourceResolvable.java | 5 +- .../support/NotificationListenerHolder.java | 7 +- .../testfixture/cache/beans/TestEntity.java | 4 +- .../core/annotation/RepeatableContainers.java | 3 +- .../core/convert/Property.java | 3 +- .../core/env/PropertySource.java | 4 +- .../org/springframework/util/ObjectUtils.java | 155 ++++------ .../util/ObjectUtilsTests.java | 271 +++++++++--------- .../simp/user/MultiServerUserRegistry.java | 3 +- .../messaging/support/GenericMessage.java | 2 +- .../simp/user/TestSimpSubscription.java | 4 +- .../springframework/r2dbc/core/Parameter.java | 2 +- .../http/ContentDisposition.java | 11 +- .../org/springframework/http/HttpEntity.java | 4 +- .../org/springframework/http/HttpRange.java | 4 +- .../springframework/http/ProblemDetail.java | 10 +- .../web/util/HierarchicalUriComponents.java | 11 +- .../web/util/OpaqueUriComponents.java | 6 +- .../web/reactive/socket/CloseStatus.java | 4 +- .../web/socket/CloseStatus.java | 3 +- 38 files changed, 276 insertions(+), 322 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java index c6ee43b2ec2..1b33b112258 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java @@ -525,11 +525,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut @Override public int hashCode() { - int hashCode = ObjectUtils.nullSafeHashCode(getExpression()); - hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutDeclarationScope); - hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterNames); - hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterTypes); - return hashCode; + return ObjectUtils.nullSafeHash(getExpression(), this.pointcutDeclarationScope, + this.pointcutParameterNames, this.pointcutParameterTypes); } @Override diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java index bc6de396395..d6ddae26719 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/TypePatternClassFilter.java @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj; +import java.util.Objects; + import org.aspectj.weaver.tools.PointcutParser; import org.aspectj.weaver.tools.TypePatternMatcher; @@ -124,7 +126,7 @@ public class TypePatternClassFilter implements ClassFilter { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.typePattern); + return Objects.hashCode(this.typePattern); } @Override diff --git a/spring-aop/src/main/java/org/springframework/aop/support/ClassFilters.java b/spring-aop/src/main/java/org/springframework/aop/support/ClassFilters.java index fa24bb10504..5b7f3b055d1 100644 --- a/spring-aop/src/main/java/org/springframework/aop/support/ClassFilters.java +++ b/spring-aop/src/main/java/org/springframework/aop/support/ClassFilters.java @@ -129,7 +129,7 @@ public abstract class ClassFilters { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.filters); + return Arrays.hashCode(this.filters); } @Override @@ -170,7 +170,7 @@ public abstract class ClassFilters { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.filters); + return Arrays.hashCode(this.filters); } @Override diff --git a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java index 4c789587955..5bb7929b2dc 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java @@ -17,6 +17,7 @@ package org.springframework.aop.target; import java.io.Serializable; +import java.util.Objects; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -190,7 +191,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour @Override public int hashCode() { - return getClass().hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.targetBeanName); + return Objects.hash(getClass(), this.targetBeanName); } @Override diff --git a/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java b/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java index 1486cff2a9a..6b0fdfd4984 100644 --- a/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java +++ b/spring-aop/src/main/java/org/springframework/aop/target/EmptyTargetSource.java @@ -17,6 +17,7 @@ package org.springframework.aop.target; import java.io.Serializable; +import java.util.Objects; import org.springframework.aop.TargetSource; import org.springframework.lang.Nullable; @@ -140,7 +141,7 @@ public final class EmptyTargetSource implements TargetSource, Serializable { @Override public int hashCode() { - return EmptyTargetSource.class.hashCode() * 13 + ObjectUtils.nullSafeHashCode(this.targetClass); + return Objects.hash(getClass(), this.targetClass); } @Override diff --git a/spring-aspects/src/test/java/org/springframework/cache/config/TestEntity.java b/spring-aspects/src/test/java/org/springframework/cache/config/TestEntity.java index 62d78b7159b..0219086ed48 100644 --- a/spring-aspects/src/test/java/org/springframework/cache/config/TestEntity.java +++ b/spring-aspects/src/test/java/org/springframework/cache/config/TestEntity.java @@ -16,6 +16,8 @@ package org.springframework.cache.config; +import java.util.Objects; + import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; @@ -42,7 +44,7 @@ public class TestEntity { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.id); + return Objects.hashCode(this.id); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanMetadataAttribute.java b/spring-beans/src/main/java/org/springframework/beans/BeanMetadataAttribute.java index 28d09d49ff0..f5c8a854ad4 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanMetadataAttribute.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanMetadataAttribute.java @@ -90,7 +90,7 @@ public class BeanMetadataAttribute implements BeanMetadataElement { @Override public int hashCode() { - return this.name.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.value); + return ObjectUtils.nullSafeHash(this.name, this.value); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java index 76ef87f3fad..df2f1333374 100644 --- a/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java +++ b/spring-beans/src/main/java/org/springframework/beans/ExtendedBeanInfo.java @@ -30,6 +30,7 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; @@ -345,7 +346,7 @@ class ExtendedBeanInfo implements BeanInfo { @Override public int hashCode() { - return (ObjectUtils.nullSafeHashCode(getReadMethod()) * 29 + ObjectUtils.nullSafeHashCode(getWriteMethod())); + return Objects.hash(getReadMethod(), getWriteMethod()); } @Override @@ -500,11 +501,8 @@ class ExtendedBeanInfo implements BeanInfo { @Override public int hashCode() { - int hashCode = ObjectUtils.nullSafeHashCode(getReadMethod()); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getWriteMethod()); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getIndexedReadMethod()); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getIndexedWriteMethod()); - return hashCode; + return Objects.hash(getReadMethod(), getWriteMethod(), + getIndexedReadMethod(), getIndexedWriteMethod()); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java b/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java index 017b7bb12c6..b7d4c18a436 100644 --- a/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java +++ b/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java @@ -20,6 +20,7 @@ import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import org.apache.commons.logging.LogFactory; @@ -30,7 +31,6 @@ import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -172,10 +172,7 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor { @Override public int hashCode() { - int hashCode = getBeanClass().hashCode(); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getReadMethod()); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getWriteMethod()); - return hashCode; + return Objects.hash(getBeanClass(), getReadMethod(), getWriteMethod()); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java b/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java index b9f374e93f1..00f567b0f67 100644 --- a/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java +++ b/spring-beans/src/main/java/org/springframework/beans/PropertyValue.java @@ -197,7 +197,7 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri @Override public int hashCode() { - return this.name.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.value); + return ObjectUtils.nullSafeHash(this.name, this.value); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java b/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java index eed896e1b4f..0a4731f904c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/InjectionPoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Member; +import java.util.Objects; import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; @@ -190,7 +191,7 @@ public class InjectionPoint { @Override public int hashCode() { - return (this.field != null ? this.field.hashCode() : ObjectUtils.nullSafeHashCode(this.methodParameter)); + return Objects.hash(this.field, this.methodParameter); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionHolder.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionHolder.java index 36a56cae9d9..92da17f3558 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionHolder.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionHolder.java @@ -173,10 +173,8 @@ public class BeanDefinitionHolder implements BeanMetadataElement { @Override public int hashCode() { - int hashCode = this.beanDefinition.hashCode(); - hashCode = 29 * hashCode + this.beanName.hashCode(); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.aliases); - return hashCode; + return ObjectUtils.nullSafeHash(this.beanDefinition, this.beanName, + this.aliases); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java index 7c240653ebb..175f5a4c0ba 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java @@ -606,7 +606,7 @@ public class ConstructorArgumentValues { * same content to reside in the same Set. */ private int contentHashCode() { - return ObjectUtils.nullSafeHashCode(this.value) * 29 + ObjectUtils.nullSafeHashCode(this.type); + return ObjectUtils.nullSafeHash(this.value, this.type); } /** diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java index 79b91cfe10b..1471f69200c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/TypedStringValue.java @@ -223,7 +223,7 @@ public class TypedStringValue implements BeanMetadataElement { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.value) * 29 + ObjectUtils.nullSafeHashCode(this.targetType); + return ObjectUtils.nullSafeHash(this.value, this.targetType); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java index e0880d60cbc..d250320dded 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java @@ -113,9 +113,7 @@ public abstract class MethodOverride implements BeanMetadataElement { @Override public int hashCode() { - int hashCode = ObjectUtils.nullSafeHashCode(this.methodName); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.source); - return hashCode; + return ObjectUtils.nullSafeHash(this.methodName, this.source); } } diff --git a/spring-context-support/src/main/java/org/springframework/mail/SimpleMailMessage.java b/spring-context-support/src/main/java/org/springframework/mail/SimpleMailMessage.java index 81657e90453..d86db63adb0 100644 --- a/spring-context-support/src/main/java/org/springframework/mail/SimpleMailMessage.java +++ b/spring-context-support/src/main/java/org/springframework/mail/SimpleMailMessage.java @@ -236,14 +236,8 @@ public class SimpleMailMessage implements MailMessage, Serializable { @Override public int hashCode() { - int hashCode = ObjectUtils.nullSafeHashCode(this.from); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.replyTo); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.to); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.cc); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.bcc); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.sentDate); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.subject); - return hashCode; + return ObjectUtils.nullSafeHash(this.from, this.replyTo, this.to, this.cc, + this.bcc, this.sentDate, this.subject); } @Override diff --git a/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java b/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java index 43b6ddd89d7..f22e0ceb721 100644 --- a/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java +++ b/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; @@ -404,7 +405,7 @@ public abstract class AbstractApplicationEventMulticaster @Override public int hashCode() { - return this.eventType.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.sourceType); + return Objects.hash(this.eventType, this.sourceType); } @Override diff --git a/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java b/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java index 7589409bde1..342839892a8 100644 --- a/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java +++ b/spring-context/src/main/java/org/springframework/context/support/ApplicationListenerDetector.java @@ -17,6 +17,7 @@ package org.springframework.context.support; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; @@ -28,7 +29,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.lang.Nullable; -import org.springframework.util.ObjectUtils; /** * {@code BeanPostProcessor} that detects beans which implement the {@code ApplicationListener} @@ -120,7 +120,7 @@ class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.applicationContext); + return Objects.hashCode(this.applicationContext); } } diff --git a/spring-context/src/main/java/org/springframework/context/support/DefaultMessageSourceResolvable.java b/spring-context/src/main/java/org/springframework/context/support/DefaultMessageSourceResolvable.java index 281b8e7986d..df09bc8957f 100644 --- a/spring-context/src/main/java/org/springframework/context/support/DefaultMessageSourceResolvable.java +++ b/spring-context/src/main/java/org/springframework/context/support/DefaultMessageSourceResolvable.java @@ -179,10 +179,7 @@ public class DefaultMessageSourceResolvable implements MessageSourceResolvable, @Override public int hashCode() { - int hashCode = ObjectUtils.nullSafeHashCode(getCodes()); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getArguments()); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getDefaultMessage()); - return hashCode; + return ObjectUtils.nullSafeHash(getCode(), getArguments(), getDefaultMessage()); } } diff --git a/spring-context/src/main/java/org/springframework/jmx/support/NotificationListenerHolder.java b/spring-context/src/main/java/org/springframework/jmx/support/NotificationListenerHolder.java index 6866af03710..9244be32ced 100644 --- a/spring-context/src/main/java/org/springframework/jmx/support/NotificationListenerHolder.java +++ b/spring-context/src/main/java/org/springframework/jmx/support/NotificationListenerHolder.java @@ -167,11 +167,8 @@ public class NotificationListenerHolder { @Override public int hashCode() { - int hashCode = ObjectUtils.nullSafeHashCode(this.notificationListener); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.notificationFilter); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.handback); - hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.mappedObjectNames); - return hashCode; + return ObjectUtils.nullSafeHash(this.notificationListener, this.notificationFilter, + this.handback, this.mappedObjectNames); } } diff --git a/spring-context/src/testFixtures/java/org/springframework/context/testfixture/cache/beans/TestEntity.java b/spring-context/src/testFixtures/java/org/springframework/context/testfixture/cache/beans/TestEntity.java index 7a9d36fb415..4fd7e9c0456 100644 --- a/spring-context/src/testFixtures/java/org/springframework/context/testfixture/cache/beans/TestEntity.java +++ b/spring-context/src/testFixtures/java/org/springframework/context/testfixture/cache/beans/TestEntity.java @@ -16,6 +16,8 @@ package org.springframework.context.testfixture.cache.beans; +import java.util.Objects; + import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; @@ -38,7 +40,7 @@ public class TestEntity { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.id); + return Objects.hashCode(this.id); } @Override diff --git a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java index 7d9f4b135c4..581ffeb9c8b 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java @@ -20,6 +20,7 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; import java.lang.reflect.Method; import java.util.Map; +import java.util.Objects; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -91,7 +92,7 @@ public abstract class RepeatableContainers { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.parent); + return Objects.hashCode(this.parent); } diff --git a/spring-core/src/main/java/org/springframework/core/convert/Property.java b/spring-core/src/main/java/org/springframework/core/convert/Property.java index 1e774106cd2..e0b601cdd46 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/Property.java +++ b/spring-core/src/main/java/org/springframework/core/convert/Property.java @@ -22,6 +22,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; @@ -269,7 +270,7 @@ public final class Property { @Override public int hashCode() { - return (ObjectUtils.nullSafeHashCode(this.objectType) * 31 + ObjectUtils.nullSafeHashCode(this.name)); + return Objects.hash(this.objectType, this.name); } } diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertySource.java b/spring-core/src/main/java/org/springframework/core/env/PropertySource.java index 64ad2c0d928..3135f072200 100644 --- a/spring-core/src/main/java/org/springframework/core/env/PropertySource.java +++ b/spring-core/src/main/java/org/springframework/core/env/PropertySource.java @@ -16,6 +16,8 @@ package org.springframework.core.env; +import java.util.Objects; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -147,7 +149,7 @@ public abstract class PropertySource { */ @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(getName()); + return Objects.hashCode(getName()); } /** 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 db8aa1ebeba..493ae8d6e6a 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -22,6 +22,7 @@ import java.time.ZoneId; import java.util.Arrays; import java.util.Collection; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.StringJoiner; import java.util.TimeZone; @@ -390,21 +391,32 @@ public abstract class ObjectUtils { } /** - * Return as hash code for the given object; typically the value of + * Return a hash code for the given elements, delegating to + * {@link #nullSafeHashCode(Object)} for each element. Contrary + * to {@link Objects#hash(Object...)}, this method handle an + * element that is an array. + * @param elements the elements to be hashed + * @return a hash value of the elements + * @since 6.1 + */ + public static int nullSafeHash(@Nullable Object... elements) { + if (elements == null) { + return 0; + } + int result = 1; + for (Object element : elements) { + result = 31 * result + nullSafeHashCode(element); + } + return result; + } + + /** + * Return a hash code for the given object; typically the value of * {@code Object#hashCode()}}. If the object is an array, - * this method will delegate to any of the {@code nullSafeHashCode} - * methods for arrays in this class. If the object is {@code null}, - * this method returns 0. + * this method will delegate to any of the {@code Arrays#hasCode} + * methods. If the object is {@code null}, this method returns 0. * @see Object#hashCode() - * @see #nullSafeHashCode(Object[]) - * @see #nullSafeHashCode(boolean[]) - * @see #nullSafeHashCode(byte[]) - * @see #nullSafeHashCode(char[]) - * @see #nullSafeHashCode(double[]) - * @see #nullSafeHashCode(float[]) - * @see #nullSafeHashCode(int[]) - * @see #nullSafeHashCode(long[]) - * @see #nullSafeHashCode(short[]) + * @see Arrays */ public static int nullSafeHashCode(@Nullable Object obj) { if (obj == null) { @@ -412,31 +424,31 @@ public abstract class ObjectUtils { } if (obj.getClass().isArray()) { if (obj instanceof Object[] objects) { - return nullSafeHashCode(objects); + return Arrays.hashCode(objects); } if (obj instanceof boolean[] booleans) { - return nullSafeHashCode(booleans); + return Arrays.hashCode(booleans); } if (obj instanceof byte[] bytes) { - return nullSafeHashCode(bytes); + return Arrays.hashCode(bytes); } if (obj instanceof char[] chars) { - return nullSafeHashCode(chars); + return Arrays.hashCode(chars); } if (obj instanceof double[] doubles) { - return nullSafeHashCode(doubles); + return Arrays.hashCode(doubles); } if (obj instanceof float[] floats) { - return nullSafeHashCode(floats); + return Arrays.hashCode(floats); } if (obj instanceof int[] ints) { - return nullSafeHashCode(ints); + return Arrays.hashCode(ints); } if (obj instanceof long[] longs) { - return nullSafeHashCode(longs); + return Arrays.hashCode(longs); } if (obj instanceof short[] shorts) { - return nullSafeHashCode(shorts); + return Arrays.hashCode(shorts); } } return obj.hashCode(); @@ -445,136 +457,91 @@ public abstract class ObjectUtils { /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(Object[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable Object[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (Object element : array) { - hash = MULTIPLIER * hash + nullSafeHashCode(element); - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(boolean[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable boolean[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (boolean element : array) { - hash = MULTIPLIER * hash + Boolean.hashCode(element); - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(byte[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable byte[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (byte element : array) { - hash = MULTIPLIER * hash + element; - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(char[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable char[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (char element : array) { - hash = MULTIPLIER * hash + element; - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(double[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable double[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (double element : array) { - hash = MULTIPLIER * hash + Double.hashCode(element); - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(float[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable float[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (float element : array) { - hash = MULTIPLIER * hash + Float.hashCode(element); - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(int[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable int[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (int element : array) { - hash = MULTIPLIER * hash + element; - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(long[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable long[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (long element : array) { - hash = MULTIPLIER * hash + Long.hashCode(element); - } - return hash; + return Arrays.hashCode(array); } /** * Return a hash code based on the contents of the specified array. * If {@code array} is {@code null}, this method returns 0. + * @deprecated as of 6.1 in favor of {@link Arrays#hashCode(short[])} */ + @Deprecated(since = "6.1") public static int nullSafeHashCode(@Nullable short[] array) { - if (array == null) { - return 0; - } - int hash = INITIAL_HASH; - for (short element : array) { - hash = MULTIPLIER * hash + element; - } - return hash; + return Arrays.hashCode(array); } 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 8090c4be82f..99388b1b8fa 100644 --- a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java @@ -30,6 +30,7 @@ import java.nio.file.Path; import java.sql.SQLException; import java.time.LocalDate; import java.time.ZoneId; +import java.util.Arrays; import java.util.Collections; import java.util.Currency; import java.util.Date; @@ -38,6 +39,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TimeZone; @@ -379,119 +381,197 @@ class ObjectUtilsTests { } @Test - void nullSafeHashCodeWithBooleanArray() { - int expected = 31 * 7 + Boolean.TRUE.hashCode(); - expected = 31 * expected + Boolean.FALSE.hashCode(); + void nullSafeHashWithNull() { + assertThat(ObjectUtils.nullSafeHash((Object[]) null)).isEqualTo(0); + } + @Test + void nullSafeHashWithIntermediateNullElements() { + assertThat(ObjectUtils.nullSafeHash(3, null, 5)).isEqualTo(Objects.hash(3, null, 5)); + } + + @Test + @Deprecated + void nullSafeHashCodeWithNullBooleanArray() { + boolean[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated + void nullSafeHashCodeWithBooleanArray() { boolean[] array = {true, false}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithBooleanArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((boolean[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingBooleanArray() { + Object array = new boolean[] {true, false}; + int expected = ObjectUtils.nullSafeHashCode((boolean[]) array); + assertEqualHashCodes(expected, array); } @Test + @Deprecated + void nullSafeHashCodeWithNullByteArray() { + byte[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated void nullSafeHashCodeWithByteArray() { - int expected = 31 * 7 + 8; - expected = 31 * expected + 10; - byte[] array = {8, 10}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithByteArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((byte[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingByteArray() { + Object array = new byte[] {6, 39}; + int expected = ObjectUtils.nullSafeHashCode((byte[]) array); + assertEqualHashCodes(expected, array); } @Test + @Deprecated + void nullSafeHashCodeWithNullCharArray() { + char[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated void nullSafeHashCodeWithCharArray() { - int expected = 31 * 7 + 'a'; - expected = 31 * expected + 'E'; - char[] array = {'a', 'E'}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithCharArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((char[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingCharArray() { + Object array = new char[] {'l', 'M'}; + int expected = ObjectUtils.nullSafeHashCode((char[]) array); + assertEqualHashCodes(expected, array); } @Test + @Deprecated + void nullSafeHashCodeWithNullDoubleArray() { + double[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated void nullSafeHashCodeWithDoubleArray() { - long bits = Double.doubleToLongBits(8449.65); - int expected = 31 * 7 + (int) (bits ^ (bits >>> 32)); - bits = Double.doubleToLongBits(9944.923); - expected = 31 * expected + (int) (bits ^ (bits >>> 32)); - double[] array = {8449.65, 9944.923}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithDoubleArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((double[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingDoubleArray() { + Object array = new double[] {68930.993, 9022.009}; + int expected = ObjectUtils.nullSafeHashCode((double[]) array); + assertEqualHashCodes(expected, array); } @Test + @Deprecated + void nullSafeHashCodeWithNullFloatArray() { + float[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated void nullSafeHashCodeWithFloatArray() { - int expected = 31 * 7 + Float.floatToIntBits(9.6f); - expected = 31 * expected + Float.floatToIntBits(7.4f); - float[] array = {9.6f, 7.4f}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithFloatArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((float[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingFloatArray() { + Object array = new float[] {9.9f, 9.54f}; + int expected = ObjectUtils.nullSafeHashCode((float[]) array); + assertEqualHashCodes(expected, array); } @Test + @Deprecated + void nullSafeHashCodeWithNullIntArray() { + int[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated void nullSafeHashCodeWithIntArray() { - int expected = 31 * 7 + 884; - expected = 31 * expected + 340; - int[] array = {884, 340}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithIntArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((int[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingIntArray() { + Object array = new int[] {89, 32}; + int expected = ObjectUtils.nullSafeHashCode((int[]) array); + assertEqualHashCodes(expected, array); } @Test + @Deprecated + void nullSafeHashCodeWithNullLongArray() { + long[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated void nullSafeHashCodeWithLongArray() { - long lng = 7993L; - int expected = 31 * 7 + (int) (lng ^ (lng >>> 32)); - lng = 84320L; - expected = 31 * expected + (int) (lng ^ (lng >>> 32)); - long[] array = {7993L, 84320L}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test - void nullSafeHashCodeWithLongArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((long[]) null)).isEqualTo(0); + @Deprecated + void nullSafeHashCodeWithObjectBeingLongArray() { + Object array = new long[] {4389, 320}; + int expected = ObjectUtils.nullSafeHashCode((long[]) array); + assertEqualHashCodes(expected, array); + } + + @Test + @Deprecated + void nullSafeHashCodeWithNullShortArray() { + short[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); + } + + @Test + @Deprecated + void nullSafeHashCodeWithShortArray() { + short[] array = {4, 25}; + int actual = ObjectUtils.nullSafeHashCode(array); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); + } + + @Test + @Deprecated + void nullSafeHashCodeWithObjectBeingShortArray() { + Object array = new short[] {5, 3}; + int expected = ObjectUtils.nullSafeHashCode((short[]) array); + assertEqualHashCodes(expected, array); } @Test @@ -501,71 +581,21 @@ class ObjectUtilsTests { } @Test + @Deprecated void nullSafeHashCodeWithObjectArray() { - int expected = 31 * 7 + "Leia".hashCode(); - expected = 31 * expected + "Han".hashCode(); - Object[] array = {"Leia", "Han"}; int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(Arrays.hashCode(array)); } @Test + @Deprecated void nullSafeHashCodeWithObjectArrayEqualToNull() { assertThat(ObjectUtils.nullSafeHashCode((Object[]) null)).isEqualTo(0); } @Test - void nullSafeHashCodeWithObjectBeingBooleanArray() { - Object array = new boolean[] {true, false}; - int expected = ObjectUtils.nullSafeHashCode((boolean[]) array); - assertEqualHashCodes(expected, array); - } - - @Test - void nullSafeHashCodeWithObjectBeingByteArray() { - Object array = new byte[] {6, 39}; - int expected = ObjectUtils.nullSafeHashCode((byte[]) array); - assertEqualHashCodes(expected, array); - } - - @Test - void nullSafeHashCodeWithObjectBeingCharArray() { - Object array = new char[] {'l', 'M'}; - int expected = ObjectUtils.nullSafeHashCode((char[]) array); - assertEqualHashCodes(expected, array); - } - - @Test - void nullSafeHashCodeWithObjectBeingDoubleArray() { - Object array = new double[] {68930.993, 9022.009}; - int expected = ObjectUtils.nullSafeHashCode((double[]) array); - assertEqualHashCodes(expected, array); - } - - @Test - void nullSafeHashCodeWithObjectBeingFloatArray() { - Object array = new float[] {9.9f, 9.54f}; - int expected = ObjectUtils.nullSafeHashCode((float[]) array); - assertEqualHashCodes(expected, array); - } - - @Test - void nullSafeHashCodeWithObjectBeingIntArray() { - Object array = new int[] {89, 32}; - int expected = ObjectUtils.nullSafeHashCode((int[]) array); - assertEqualHashCodes(expected, array); - } - - @Test - void nullSafeHashCodeWithObjectBeingLongArray() { - Object array = new long[] {4389, 320}; - int expected = ObjectUtils.nullSafeHashCode((long[]) array); - assertEqualHashCodes(expected, array); - } - - @Test + @Deprecated void nullSafeHashCodeWithObjectBeingObjectArray() { Object array = new Object[] {"Luke", "Anakin"}; int expected = ObjectUtils.nullSafeHashCode((Object[]) array); @@ -573,31 +603,10 @@ class ObjectUtilsTests { } @Test - void nullSafeHashCodeWithObjectBeingShortArray() { - Object array = new short[] {5, 3}; - int expected = ObjectUtils.nullSafeHashCode((short[]) array); - assertEqualHashCodes(expected, array); - } - - @Test + @Deprecated void nullSafeHashCodeWithObjectEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((Object) null)).isEqualTo(0); - } - - @Test - void nullSafeHashCodeWithShortArray() { - int expected = 31 * 7 + 70; - expected = 31 * expected + 8; - - short[] array = {70, 8}; - int actual = ObjectUtils.nullSafeHashCode(array); - - assertThat(actual).isEqualTo(expected); - } - - @Test - void nullSafeHashCodeWithShortArrayEqualToNull() { - assertThat(ObjectUtils.nullSafeHashCode((short[]) null)).isEqualTo(0); + Object[] array = null; + assertThat(ObjectUtils.nullSafeHashCode(array)).isEqualTo(0); } @Test diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java index 6973f11b85a..4dad562b318 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/MultiServerUserRegistry.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -539,7 +540,7 @@ public class MultiServerUserRegistry implements SimpUserRegistry, SmartApplicati @Override public int hashCode() { - return getId().hashCode() * 31 + ObjectUtils.nullSafeHashCode(getSession()); + return Objects.hash(getId(), getSession()); } @Override diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/GenericMessage.java b/spring-messaging/src/main/java/org/springframework/messaging/support/GenericMessage.java index b81401a94b6..72b06f560ad 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/GenericMessage.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/GenericMessage.java @@ -98,7 +98,7 @@ public class GenericMessage implements Message, Serializable { @Override public int hashCode() { // Using nullSafeHashCode for proper array hashCode handling - return ObjectUtils.nullSafeHashCode(this.payload) * 23 + this.headers.hashCode(); + return ObjectUtils.nullSafeHash(this.payload, this.headers); } @Override diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/user/TestSimpSubscription.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/user/TestSimpSubscription.java index 1cc9ffb5767..bad87cf42c4 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/user/TestSimpSubscription.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/user/TestSimpSubscription.java @@ -16,6 +16,8 @@ package org.springframework.messaging.simp.user; +import java.util.Objects; + import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; @@ -66,7 +68,7 @@ public class TestSimpSubscription implements SimpSubscription { @Override public int hashCode() { - return this.id.hashCode() * 31 + ObjectUtils.nullSafeHashCode(getSession()); + return Objects.hash(this.id, getSession()); } @Override diff --git a/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/Parameter.java b/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/Parameter.java index 453415b659f..7d0d482fac1 100644 --- a/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/Parameter.java +++ b/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/Parameter.java @@ -117,7 +117,7 @@ public final class Parameter { @Override public int hashCode() { - return ObjectUtils.nullSafeHashCode(this.value) + ObjectUtils.nullSafeHashCode(this.type); + return ObjectUtils.nullSafeHash(this.value, this.type); } @Override diff --git a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java index 5600bb16e4a..e2f1cdecb6b 100644 --- a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java +++ b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java @@ -240,15 +240,8 @@ public final class ContentDisposition { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(this.type); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.name); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.filename); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.charset); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.size); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.creationDate); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.modificationDate); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.readDate); - return result; + return ObjectUtils.nullSafeHash(this.type, this.name,this.filename, + this.charset, this.size, this.creationDate, this.modificationDate, this.readDate); } /** diff --git a/spring-web/src/main/java/org/springframework/http/HttpEntity.java b/spring-web/src/main/java/org/springframework/http/HttpEntity.java index 9b5be7c625a..b3203e4e05d 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpEntity.java +++ b/spring-web/src/main/java/org/springframework/http/HttpEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -141,7 +141,7 @@ public class HttpEntity { @Override public int hashCode() { - return (ObjectUtils.nullSafeHashCode(this.headers) * 29 + ObjectUtils.nullSafeHashCode(this.body)); + return ObjectUtils.nullSafeHash(this.headers, this.body); } @Override diff --git a/spring-web/src/main/java/org/springframework/http/HttpRange.java b/spring-web/src/main/java/org/springframework/http/HttpRange.java index 9c0ecc68649..bc1d966657a 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpRange.java +++ b/spring-web/src/main/java/org/springframework/http/HttpRange.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.StringJoiner; import org.springframework.core.io.InputStreamResource; @@ -276,8 +277,7 @@ public abstract class HttpRange { @Override public int hashCode() { - return (ObjectUtils.nullSafeHashCode(this.firstPos) * 31 + - ObjectUtils.nullSafeHashCode(this.lastPos)); + return Objects.hash(this.firstPos, this.lastPos); } @Override diff --git a/spring-web/src/main/java/org/springframework/http/ProblemDetail.java b/spring-web/src/main/java/org/springframework/http/ProblemDetail.java index cbe60aa353e..37f2b6ce80c 100644 --- a/spring-web/src/main/java/org/springframework/http/ProblemDetail.java +++ b/spring-web/src/main/java/org/springframework/http/ProblemDetail.java @@ -19,6 +19,7 @@ package org.springframework.http; import java.net.URI; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -244,13 +245,8 @@ public class ProblemDetail { @Override public int hashCode() { - int result = this.type.hashCode(); - result = 31 * result + ObjectUtils.nullSafeHashCode(getTitle()); - result = 31 * result + this.status; - result = 31 * result + ObjectUtils.nullSafeHashCode(this.detail); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.instance); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.properties); - return result; + return Objects.hash(this.type, getTitle(), this.status, this.detail, + this.instance, this.properties); } @Override diff --git a/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java b/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java index 7314cf92eb9..d3f0229b373 100644 --- a/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java +++ b/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java @@ -24,6 +24,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.StringJoiner; import java.util.function.BiFunction; import java.util.function.UnaryOperator; @@ -566,14 +567,8 @@ final class HierarchicalUriComponents extends UriComponents { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(getScheme()); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.userInfo); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.host); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.port); - result = 31 * result + this.path.hashCode(); - result = 31 * result + this.queryParams.hashCode(); - result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment()); - return result; + return Objects.hash(getScheme(), this.userInfo, this.host, this.port, + this.path, this.queryParams, getFragment()); } diff --git a/spring-web/src/main/java/org/springframework/web/util/OpaqueUriComponents.java b/spring-web/src/main/java/org/springframework/web/util/OpaqueUriComponents.java index 3c886b45238..de437e6db0f 100644 --- a/spring-web/src/main/java/org/springframework/web/util/OpaqueUriComponents.java +++ b/spring-web/src/main/java/org/springframework/web/util/OpaqueUriComponents.java @@ -21,6 +21,7 @@ import java.net.URISyntaxException; import java.nio.charset.Charset; import java.util.Collections; import java.util.List; +import java.util.Objects; import org.springframework.lang.Nullable; import org.springframework.util.LinkedMultiValueMap; @@ -166,10 +167,7 @@ final class OpaqueUriComponents extends UriComponents { @Override public int hashCode() { - int result = ObjectUtils.nullSafeHashCode(getScheme()); - result = 31 * result + ObjectUtils.nullSafeHashCode(this.ssp); - result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment()); - return result; + return Objects.hash(getScheme(), this.ssp, getFragment()); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/socket/CloseStatus.java b/spring-webflux/src/main/java/org/springframework/web/reactive/socket/CloseStatus.java index 4d3d5f8569d..2ca52cacb3f 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/socket/CloseStatus.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/socket/CloseStatus.java @@ -16,6 +16,8 @@ package org.springframework.web.reactive.socket; +import java.util.Objects; + import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -231,7 +233,7 @@ public final class CloseStatus { @Override public int hashCode() { - return this.code * 29 + ObjectUtils.nullSafeHashCode(this.reason); + return Objects.hash(this.code, this.reason); } @Override diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/CloseStatus.java b/spring-websocket/src/main/java/org/springframework/web/socket/CloseStatus.java index 70192c72fba..1c95288c398 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/CloseStatus.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/CloseStatus.java @@ -17,6 +17,7 @@ package org.springframework.web.socket; import java.io.Serializable; +import java.util.Objects; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -213,7 +214,7 @@ public final class CloseStatus implements Serializable { @Override public int hashCode() { - return this.code * 29 + ObjectUtils.nullSafeHashCode(this.reason); + return Objects.hash(this.code, this.reason); } @Override