fix: ignore Kotlin DefaultConstructorMarker in BeanUtils#getParametersName (#34760)

Mismatch caused by DefaultConstructorMarker, which is now filtered out.
Signed-off-by: EmilSt <hesongyi2002@gmail.com>
This commit is contained in:
EmilSt 2025-05-07 12:55:31 +01:00
parent d8b506e09a
commit 5350aeaad9
2 changed files with 69 additions and 1 deletions

View File

@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Set;
import kotlin.jvm.JvmClassMappingKt;
import kotlin.jvm.internal.DefaultConstructorMarker;
import kotlin.reflect.KClass;
import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter;
@ -659,7 +660,13 @@ public abstract class BeanUtils {
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
@Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
Assert.state(paramNames.length == ctor.getParameterCount(),
// The generated param "DefaultConstructorMarker" is used to avoid collision of signatures
// and should be filtered out
long realParamsCount = Arrays.stream(ctor.getParameters())
.filter(p -> !DefaultConstructorMarker.class.equals(p.getType()))
.count();
Assert.state(paramNames.length == realParamsCount,
() -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor);
return paramNames;
}

View File

@ -157,6 +157,67 @@ class BeanUtilsKotlinTests {
assertThat(instance).isEqualTo(ConstructorWithNullablePrimitiveValueClass(null))
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with Foo`() {
val ctor = BeanUtils.findPrimaryConstructor(Foo::class.java)!!
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("param1", "param2")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with Bar`() {
val ctor = BeanUtils.findPrimaryConstructor(Bar::class.java)!!
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("param1", "param2")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with Baz`() {
val ctor = BeanUtils.findPrimaryConstructor(Baz::class.java)!!
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("param1", "param2")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with Qux`() {
val ctor = BeanUtils.findPrimaryConstructor(Qux::class.java)!!
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("param1", "param2")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithValueClass`() {
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithValueClass::class.java)!!
assertThat(ctor).isNotNull()
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("value")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithNullableValueClass`() {
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithNullableValueClass::class.java)!!
assertThat(ctor).isNotNull()
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("value")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithPrimitiveValueClass`() {
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithPrimitiveValueClass::class.java)!!
assertThat(ctor).isNotNull()
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("value")
}
@Test
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithNullablePrimitiveValueClass`() {
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithNullablePrimitiveValueClass::class.java)!!
assertThat(ctor).isNotNull()
val names = BeanUtils.getParameterNames(ctor)
assertThat(names).containsExactly("value")
}
class Foo(val param1: String, val param2: Int)