@@ -70,9 +70,19 @@ public abstract class BeanUtils {
7070 private static final Set <Class <?>> unknownEditorTypes =
7171 Collections .newSetFromMap (new ConcurrentReferenceHashMap <>(64 ));
7272
73- private static final boolean kotlinPresent =
74- ClassUtils .isPresent ("kotlin.Unit" , BeanUtils .class .getClassLoader ());
75-
73+ @ Nullable
74+ private static Class <?> kotlinMetadata ;
75+
76+ static {
77+ try {
78+ kotlinMetadata = ClassUtils .forName ("kotlin.Metadata" , BeanUtils .class .getClassLoader ());
79+ }
80+ catch (ClassNotFoundException ex ) {
81+ // Kotlin API not available - no special support for Kotlin class instantiation
82+ kotlinMetadata = null ;
83+ }
84+ }
85+
7686
7787 /**
7888 * Convenience method to instantiate a class using its no-arg constructor.
@@ -115,7 +125,7 @@ public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationExc
115125 throw new BeanInstantiationException (clazz , "Specified class is an interface" );
116126 }
117127 try {
118- Constructor <T > ctor = (kotlinPresent && isKotlinClass (clazz ) ?
128+ Constructor <T > ctor = (isKotlinClass (clazz ) ?
119129 KotlinDelegate .findPrimaryConstructor (clazz ) : clazz .getDeclaredConstructor ());
120130 if (ctor == null ) {
121131 throw new BeanInstantiationException (clazz , "No default constructor found" );
@@ -152,8 +162,8 @@ public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) thro
152162 * non-accessible (that is, non-public) constructor, and supports Kotlin classes
153163 * with optional parameters and default values.
154164 * @param ctor the constructor to instantiate
155- * @param args the constructor arguments to apply (use null for unspecified parameter
156- * if needed for Kotlin classes with optional parameters and default values)
165+ * @param args the constructor arguments to apply (use {@code null} for an unspecified
166+ * parameter if needed for Kotlin classes with optional parameters and default values)
157167 * @return the new instance
158168 * @throws BeanInstantiationException if the bean cannot be instantiated
159169 * @see Constructor#newInstance
@@ -162,7 +172,8 @@ public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws
162172 Assert .notNull (ctor , "Constructor must not be null" );
163173 try {
164174 ReflectionUtils .makeAccessible (ctor );
165- return (kotlinPresent && isKotlinClass (ctor .getDeclaringClass ()) ? KotlinDelegate .instantiateClass (ctor , args ) : ctor .newInstance (args ));
175+ return (isKotlinClass (ctor .getDeclaringClass ()) ?
176+ KotlinDelegate .instantiateClass (ctor , args ) : ctor .newInstance (args ));
166177 }
167178 catch (InstantiationException ex ) {
168179 throw new BeanInstantiationException (ctor , "Is it an abstract class?" , ex );
@@ -329,8 +340,7 @@ else if (!method.isBridge() && targetMethod.getParameterCount() == numParams) {
329340 @ Nullable
330341 public static <T > Constructor <T > findPrimaryConstructor (Class <T > clazz ) {
331342 Assert .notNull (clazz , "Class must not be null" );
332- Constructor <T > ctor = null ;
333- if (kotlinPresent && isKotlinClass (clazz )) {
343+ if (isKotlinClass (clazz )) {
334344 return KotlinDelegate .findPrimaryConstructor (clazz );
335345 }
336346 else {
@@ -699,13 +709,10 @@ private static void copyProperties(Object source, Object target, @Nullable Class
699709 /**
700710 * Return true if the specified class is a Kotlin one.
701711 */
712+ @ SuppressWarnings ("unchecked" )
702713 private static boolean isKotlinClass (Class <?> clazz ) {
703- for (Annotation annotation : clazz .getDeclaredAnnotations ()) {
704- if (annotation .annotationType ().getName ().equals ("kotlin.Metadata" )) {
705- return true ;
706- }
707- }
708- return false ;
714+ return (kotlinMetadata != null &&
715+ clazz .getDeclaredAnnotation ((Class <? extends Annotation >) kotlinMetadata ) != null );
709716 }
710717
711718
@@ -717,7 +724,8 @@ private static class KotlinDelegate {
717724 /**
718725 * Return the Java constructor corresponding to the Kotlin primary constructor if any.
719726 * @param clazz the {@link Class} of the Kotlin class
720- * @see <a href="http://kotlinlang.org/docs/reference/classes.html#constructors">http://kotlinlang.org/docs/reference/classes.html#constructors</a>
727+ * @see <a href="http://kotlinlang.org/docs/reference/classes.html#constructors">
728+ * http://kotlinlang.org/docs/reference/classes.html#constructors</a>
721729 */
722730 @ Nullable
723731 public static <T > Constructor <T > findPrimaryConstructor (Class <T > clazz ) {
@@ -726,7 +734,8 @@ public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
726734 return null ;
727735 }
728736 Constructor <T > constructor = ReflectJvmMapping .getJavaConstructor (primaryConstructor );
729- Assert .notNull (constructor , "Can't get the Java constructor corresponding to the Kotlin primary constructor of " + clazz .getName ());
737+ Assert .notNull (constructor ,
738+ () -> "Failed to find Java constructor corresponding to Kotlin primary constructor: " + clazz .getName ());
730739 return constructor ;
731740 }
732741
@@ -735,14 +744,16 @@ public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
735744 * @param ctor the constructor of the Kotlin class to instantiate
736745 * @param args the constructor arguments to apply (use null for unspecified parameter if needed)
737746 */
738- public static <T > T instantiateClass (Constructor <T > ctor , Object ... args ) throws IllegalAccessException , InvocationTargetException , InstantiationException {
747+ public static <T > T instantiateClass (Constructor <T > ctor , Object ... args )
748+ throws IllegalAccessException , InvocationTargetException , InstantiationException {
749+
739750 KFunction <T > kotlinConstructor = ReflectJvmMapping .getKotlinFunction (ctor );
740751 if (kotlinConstructor == null ) {
741752 return ctor .newInstance (args );
742753 }
743754 List <KParameter > parameters = kotlinConstructor .getParameters ();
744755 Map <KParameter , Object > argParameters = new HashMap <>(parameters .size ());
745- Assert .isTrue (args .length <= parameters .size (),
756+ Assert .isTrue (args .length <= parameters .size (),
746757 "The number of provided arguments should be less of equals than the number of constructor parameters" );
747758 for (int i = 0 ; i < args .length ; i ++) {
748759 if (!(parameters .get (i ).isOptional () && (args [i ] == null ))) {
0 commit comments