Support primitive types in BeanUtils.instantiateClass args
This commit adds support for primitive default values for BeanUtils.instantiateClass arguments in Java in order to provide a consistent behavior in both Java and Kotlin languages. Closes gh-22531
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -70,6 +70,18 @@ public abstract class BeanUtils {
|
||||
private static final Set<Class<?>> unknownEditorTypes =
|
||||
Collections.newSetFromMap(new ConcurrentReferenceHashMap<>(64));
|
||||
|
||||
private static final Map<Class<?>, Object> DEFAULT_TYPE_VALUES;
|
||||
|
||||
static {
|
||||
Map<Class<?>, Object> values = new HashMap<>();
|
||||
values.put(boolean.class, false);
|
||||
values.put(byte.class, (byte) 0);
|
||||
values.put(short.class, (short) 0);
|
||||
values.put(int.class, 0);
|
||||
values.put(long.class, (long) 0);
|
||||
DEFAULT_TYPE_VALUES = Collections.unmodifiableMap(values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to instantiate a class using its no-arg constructor.
|
||||
@@ -159,7 +171,7 @@ public abstract class BeanUtils {
|
||||
* with optional parameters and default values.
|
||||
* @param ctor the constructor to instantiate
|
||||
* @param args the constructor arguments to apply (use {@code null} for an unspecified
|
||||
* parameter if needed for Kotlin classes with optional parameters and default values)
|
||||
* parameter, Kotlin optional parameters and Java primitive types are supported)
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @see Constructor#newInstance
|
||||
@@ -168,8 +180,24 @@ public abstract class BeanUtils {
|
||||
Assert.notNull(ctor, "Constructor must not be null");
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(ctor);
|
||||
return (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
|
||||
KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
|
||||
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
|
||||
return KotlinDelegate.instantiateClass(ctor, args);
|
||||
}
|
||||
else {
|
||||
Class<?>[] parameterTypes = ctor.getParameterTypes();
|
||||
Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
|
||||
Object[] argsWithDefaultValues = new Object[args.length];
|
||||
for (int i = 0 ; i < args.length; i++) {
|
||||
if (args[i] == null) {
|
||||
Class<?> parameterType = parameterTypes[i];
|
||||
argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
|
||||
}
|
||||
else {
|
||||
argsWithDefaultValues[i] = args[i];
|
||||
}
|
||||
}
|
||||
return ctor.newInstance(argsWithDefaultValues);
|
||||
}
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
|
||||
|
||||
Reference in New Issue
Block a user