@@ -225,9 +225,10 @@ public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws
225225
226226 /**
227227 * Return a resolvable constructor for the provided class, either a primary or single
228- * public constructor with arguments, or a single non-public constructor with arguments,
229- * or simply a default constructor. Callers have to be prepared to resolve arguments
230- * for the returned constructor's parameters, if any.
228+ * public constructor with arguments, a single non-public constructor with arguments
229+ * or simply a default constructor.
230+ * <p>Callers have to be prepared to resolve arguments for the returned constructor's
231+ * parameters, if any.
231232 * @param clazz the class to check
232233 * @throws IllegalStateException in case of no unique constructor found at all
233234 * @since 5.3
@@ -253,19 +254,6 @@ else if (ctors.length == 0) {
253254 return (Constructor <T >) ctors [0 ];
254255 }
255256 }
256- else if (clazz .isRecord ()) {
257- try {
258- // if record -> use canonical constructor, which is always presented
259- Class <?>[] paramTypes
260- = Arrays .stream (clazz .getRecordComponents ())
261- .map (RecordComponent ::getType )
262- .toArray (Class <?>[]::new );
263- return clazz .getDeclaredConstructor (paramTypes );
264- }
265- catch (NoSuchMethodException ex ) {
266- // Giving up with record...
267- }
268- }
269257
270258 // Several constructors -> let's try to take the default constructor
271259 try {
@@ -282,18 +270,32 @@ else if (clazz.isRecord()) {
282270 /**
283271 * Return the primary constructor of the provided class. For Kotlin classes, this
284272 * returns the Java constructor corresponding to the Kotlin primary constructor
285- * (as defined in the Kotlin specification). Otherwise, in particular for non-Kotlin
286- * classes , this simply returns {@code null}.
273+ * (as defined in the Kotlin specification). For Java records, this returns the
274+ * canonical constructor. Otherwise , this simply returns {@code null}.
287275 * @param clazz the class to check
288276 * @since 5.0
289- * @see <a href="https://kotlinlang.org/docs/reference/classes.html#constructors">Kotlin docs</a>
277+ * @see <a href="https://kotlinlang.org/docs/reference/classes.html#constructors">Kotlin constructors</a>
278+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-8.html#jls-8.10.4">Record constructor declarations</a>
290279 */
291280 @ Nullable
292281 public static <T > Constructor <T > findPrimaryConstructor (Class <T > clazz ) {
293282 Assert .notNull (clazz , "Class must not be null" );
294283 if (KotlinDetector .isKotlinReflectPresent () && KotlinDetector .isKotlinType (clazz )) {
295284 return KotlinDelegate .findPrimaryConstructor (clazz );
296285 }
286+ if (clazz .isRecord ()) {
287+ try {
288+ // Use the canonical constructor which is always present
289+ RecordComponent [] components = clazz .getRecordComponents ();
290+ Class <?>[] paramTypes = new Class <?>[components .length ];
291+ for (int i = 0 ; i < components .length ; i ++) {
292+ paramTypes [i ] = components [i ].getType ();
293+ }
294+ return clazz .getDeclaredConstructor (paramTypes );
295+ }
296+ catch (NoSuchMethodException ignored ) {
297+ }
298+ }
297299 return null ;
298300 }
299301
0 commit comments