Skip to content

Commit f37ec90

Browse files
committed
Consider Void.class a primitive wrapper in ClassUtils
Prior to this commit, ClassUtils.isPrimitiveOrWrapper() and ClassUtils.isPrimitiveWrapper() did not return true for Void.class. However, ClassUtils.isPrimitiveOrWrapper() did return true for void.class. This lacking symmetry is inconsistent and can lead to bugs in reflective code. See: spring-projects/spring-data-r2dbc#159 This commit addresses this by adding an entry for Void.class -> void.class in the internal primitiveWrapperTypeMap in ClassUtils. Closes gh-23572
1 parent f748b1e commit f37ec90

File tree

4 files changed

+56
-8
lines changed

4 files changed

+56
-8
lines changed

spring-core/src/main/java/org/springframework/util/ClassUtils.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public abstract class ClassUtils {
120120
primitiveWrapperTypeMap.put(Integer.class, int.class);
121121
primitiveWrapperTypeMap.put(Long.class, long.class);
122122
primitiveWrapperTypeMap.put(Short.class, short.class);
123+
primitiveWrapperTypeMap.put(Void.class, void.class);
123124

124125
// Map entry iteration is less expensive to initialize than forEach with lambdas
125126
for (Map.Entry<Class<?>, Class<?>> entry : primitiveWrapperTypeMap.entrySet()) {
@@ -462,7 +463,8 @@ public static Class<?> resolvePrimitiveClassName(@Nullable String name) {
462463

463464
/**
464465
* Check if the given class represents a primitive wrapper,
465-
* i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double.
466+
* i.e. Boolean, Byte, Character, Short, Integer, Long, Float, Double, or
467+
* Void.
466468
* @param clazz the class to check
467469
* @return whether the given class is a primitive wrapper class
468470
*/
@@ -473,10 +475,12 @@ public static boolean isPrimitiveWrapper(Class<?> clazz) {
473475

474476
/**
475477
* Check if the given class represents a primitive (i.e. boolean, byte,
476-
* char, short, int, long, float, or double) or a primitive wrapper
477-
* (i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double).
478+
* char, short, int, long, float, or double), {@code void}, or a wrapper for
479+
* those types (i.e. Boolean, Byte, Character, Short, Integer, Long, Float,
480+
* Double, or Void).
478481
* @param clazz the class to check
479-
* @return whether the given class is a primitive or primitive wrapper class
482+
* @return {@code true} if the given class represents a primitive, void, or
483+
* a wrapper class
480484
*/
481485
public static boolean isPrimitiveOrWrapper(Class<?> clazz) {
482486
Assert.notNull(clazz, "Class must not be null");

spring-core/src/test/java/org/springframework/util/ClassUtilsTests.java

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,14 +40,17 @@
4040
import static org.junit.Assert.*;
4141

4242
/**
43+
* Unit tests for {@link ClassUtils}.
44+
*
4345
* @author Colin Sampaleanu
4446
* @author Juergen Hoeller
4547
* @author Rob Harrop
4648
* @author Rick Evans
49+
* @author Sam Brannen
4750
*/
4851
public class ClassUtilsTests {
4952

50-
private ClassLoader classLoader = getClass().getClassLoader();
53+
private final ClassLoader classLoader = getClass().getClassLoader();
5154

5255

5356
@Before
@@ -384,6 +387,42 @@ public void testDetermineCommonAncestor() {
384387
assertNull(ClassUtils.determineCommonAncestor(String.class, List.class));
385388
}
386389

390+
@Test
391+
public void isPrimitiveWrapper() {
392+
assertTrue(ClassUtils.isPrimitiveWrapper(Boolean.class));
393+
assertTrue(ClassUtils.isPrimitiveWrapper(Character.class));
394+
assertTrue(ClassUtils.isPrimitiveWrapper(Byte.class));
395+
assertTrue(ClassUtils.isPrimitiveWrapper(Short.class));
396+
assertTrue(ClassUtils.isPrimitiveWrapper(Integer.class));
397+
assertTrue(ClassUtils.isPrimitiveWrapper(Long.class));
398+
assertTrue(ClassUtils.isPrimitiveWrapper(Float.class));
399+
assertTrue(ClassUtils.isPrimitiveWrapper(Double.class));
400+
assertTrue(ClassUtils.isPrimitiveWrapper(Void.class));
401+
}
402+
403+
@Test
404+
public void isPrimitiveOrWrapper() {
405+
assertTrue(ClassUtils.isPrimitiveOrWrapper(boolean.class));
406+
assertTrue(ClassUtils.isPrimitiveOrWrapper(char.class));
407+
assertTrue(ClassUtils.isPrimitiveOrWrapper(byte.class));
408+
assertTrue(ClassUtils.isPrimitiveOrWrapper(short.class));
409+
assertTrue(ClassUtils.isPrimitiveOrWrapper(int.class));
410+
assertTrue(ClassUtils.isPrimitiveOrWrapper(long.class));
411+
assertTrue(ClassUtils.isPrimitiveOrWrapper(float.class));
412+
assertTrue(ClassUtils.isPrimitiveOrWrapper(double.class));
413+
assertTrue(ClassUtils.isPrimitiveOrWrapper(void.class));
414+
415+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Boolean.class));
416+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Character.class));
417+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Byte.class));
418+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Short.class));
419+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Integer.class));
420+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Long.class));
421+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Float.class));
422+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Double.class));
423+
assertTrue(ClassUtils.isPrimitiveOrWrapper(Void.class));
424+
}
425+
387426

388427
public static class InnerClass {
389428

spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public boolean supports(HandlerResult result) {
162162

163163
return (CharSequence.class.isAssignableFrom(type) || Rendering.class.isAssignableFrom(type) ||
164164
Model.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) ||
165-
void.class.equals(type) || View.class.isAssignableFrom(type) ||
165+
Void.class.equals(type) || void.class.equals(type) || View.class.isAssignableFrom(type) ||
166166
!BeanUtils.isSimpleProperty(type));
167167
}
168168

spring-webflux/src/test/java/org/springframework/web/reactive/result/view/ViewResolutionResultHandlerTests.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,12 @@ private void testDoesNotSupport(MethodParameter returnType) {
114114
private void testSupports(MethodParameter returnType, boolean supports) {
115115
ViewResolutionResultHandler resultHandler = resultHandler(mock(ViewResolver.class));
116116
HandlerResult handlerResult = new HandlerResult(new Object(), null, returnType, this.bindingContext);
117-
assertEquals(supports, resultHandler.supports(handlerResult));
117+
if (supports) {
118+
assertTrue("return type [" + returnType + "] should be supported", resultHandler.supports(handlerResult));
119+
}
120+
else {
121+
assertFalse("return type [" + returnType + "] should not be supported", resultHandler.supports(handlerResult));
122+
}
118123
}
119124

120125
@Test

0 commit comments

Comments
 (0)