1. Introduction

When working with Kotlin, it is sometimes necessary to get a KClass instance from a package class name string. Whether it’s for dynamic instantiation or method invocation, having the ability to convert a class name string to its corresponding KClass object is crucial. The KClass object represents a Kotlin class at runtime and can be obtained with several strategies.

In this tutorial, we’ll explore different ways to get a KClass from a package class name string in Kotlin.

2. Using the Class.forName() Method

Java’s reflection API provides the most straightforward way to obtain a KClass from a class name string via the Class.forName() method. Once we have the class, we can use the kotlin property to get the KClass instance:

fun getClassUsingForName(className: String): KClass<*>? {
    return Class.forName(className).kotlin
}

We can use this helper method to get the KClass instance for any class by its name. The Class.forName() method loads the class dynamically at runtime based on the provided class name String.

Let’s verify the behavior of our getClassUsingForName() helper method. We provide it with a class name and assert that we obtain the correct KClass:

 @Test
 fun `obtain the Kclass from Package Class name using forName method`() {
    val className = "com.baeldung.obtainKclassFromPackageClassName.ClassExample"

    val kClass = getClassUsingForName(className)

    assertEquals(ClassExample::class, kClass)
}

Additionally, this approach throws a ClassNotFoundException if the class is not found:

@Test
fun `obtain the Kclass from Package Class name using forName method and non-existing class`() {
    val notClass = "com.baeldung.obtainKclassFromPackageClassName.NotAClass"

    val exception = assertThrows<ClassNotFoundException> {
        getClassUsingForName(notClass)
    }

    assertEquals("com.baeldung.obtainKclassFromPackageClassName.NotAClass", exception.message)
}

3. Using the ClassLoader.loadClass() Method

Another way to get a KClass instance from a package class name string is to use the ClassLoader.loadClass() method:

fun getClassFromLoader(className: String): KClass<*>? {
        ClassLoader.getSystemClassLoader().loadClass(className).kotlin
}

By using the system class loader’s loadClass() method, we load the class dynamically and then retrieve its KClass object:

@Test
fun `obtain the Kclass from Package Class name using class loader`() {
    val className = "com.baeldung.obtainKclassFromPackageClassName.ClassExample"

    val kClass = getClassFromLoader(className)

    assertEquals(ClassExample::class, kClass)
}

This verifies that the getClassFromLoader() function successfully loads the KClass by the fully qualified name.

Similarly, we see that our helper method throws a ClassNotFoundException when we use a class name that doesn’t exist:

@Test
fun `obtain the Kclass from Package Class name using class loader and non-existing class`() {
    val notClass = "com.baeldung.obtainKclassFromPackageClassName.NotAClass"
        
    val exception = assertThrows<ClassNotFoundException> {
        getClassFromLoader(notClass)
    }

    assertEquals("com.baeldung.obtainKclassFromPackageClassName.NotAClass", exception.message)
}

4. Using ClassGraph Library

Finally, the ClassGraph library offers another way to obtain class information from class name strings. ClassGraph provides utilities for scanning the classpath and accessing class metadata:

fun getClassUsingClassGraph(className: String): KClass<*>? {
    val classInfo: ClassInfo? = ClassGraph()
        .addClassLoader(ClassLoader.getSystemClassLoader())
        .enableClassInfo()
        .scan()
        .getClassInfo(className)

    return classInfo?.loadClass()?.kotlin
}

Using the ClassGraph library, our helper method loads a class by its name. Specifically, we check if the provided class name exists by calling the getClassInfo() method. Finally, we’ll get the corresponding KClass:

@Test
fun `obtain the Kclass from Package Class name using class path`() {
    val className = "com.baeldung.obtainKclassFromPackageClassName.ClassExample"
    val kClass = getClassUsingClassGraph(className)

    assertEquals(ClassExample::class, kClass)
}

If the class name provided doesn’t exist, we’ll receive null instead:

@Test
fun `obtain the Kclass from Package Class name using class path and non-existing class`() {
    val notClass = "com.baeldung.obtainKclassFromPackageClassName.NotAClass"
    val kClass = getClassUsingClassGraph(notClass)

    assertNull(kClass) 
}

5. Conclusion

In this article, we’ve explored various ways to obtain the KClass object from a package class name string in Kotlin. We started with strategies from core Java, with the traditional Class.forName() and ClassLoader methods. Finally, we looked at the ClassGraph library in case we want more advanced utilities. Each approach offers distinct advantages depending on the project’s requirements and preferences.

By mastering these techniques, we can dynamically access Kotlin classes from their fully qualified package string for dynamic instantiation, method invocation, or classpath scanning.

As always, the complete source code used in this article is available over on GitHub.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments