Skip to content

fix: handle Kotlin enum constant subclass (isAnonymousClass==false) in TypeHandlerRegistry#3659

Open
wangshuai67 wants to merge 1 commit intomybatis:masterfrom
wangshuai67:fix/kotlin-enum-anonymous-class-type-handler
Open

fix: handle Kotlin enum constant subclass (isAnonymousClass==false) in TypeHandlerRegistry#3659
wangshuai67 wants to merge 1 commit intomybatis:masterfrom
wangshuai67:fix/kotlin-enum-anonymous-class-type-handler

Conversation

@wangshuai67
Copy link
Copy Markdown

Problem

Fixes #3658

In Kotlin, when an enum constant overrides an abstract method, the Kotlin compiler generates a subclass of the enum with the constant's behavior. Unlike Java's behavior, Class.isAnonymousClass() returns alse for these generated subclasses in Kotlin.

This causes TypeHandlerRegistry to fail when looking up TypeHandler for such Kotlin enum constants, because the registry uses isAnonymousClass() as the sole signal to detect "this is an enum constant subclass, look at the parent":

java // Before (line 307) - misses Kotlin enum constant subclasses Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;

Reproduction (Kotlin)

`kotlin
enum class TestEnum {
TEST1 {
override fun test() = println("test1")
};
abstract fun test()
}

fun main() {
println(TestEnum.TEST1::class.java.isAnonymousClass) // false in Kotlin!
println(TestEnum.TEST1.javaClass.superclass == TestEnum::class.java) // true
}
`

When MyBatis tries to resolve a TypeHandler for TestEnum.TEST1, it gets the generated subclass (not TestEnum), fails to find a handler, and the mapping breaks.

Fix

getSmartHandler (line 307)

Add a secondary check: if clazz.getSuperclass().isEnum() is true, the class is an enum constant's body subclass regardless of isAnonymousClass().

java // After - handles both Java and Kotlin Class<?> enumClass = (clazz.isAnonymousClass() || (clazz.getSuperclass() != null && clazz.getSuperclass().isEnum())) ? clazz.getSuperclass() : clazz;

getJdbcHandlerMap (line 331)

Add a branch to look up the handler map via the parent enum class when the class is a Kotlin-style enum subclass.

java } else if (clazz.getSuperclass() != null && clazz.getSuperclass().isEnum()) { jdbcHandlerMap = typeHandlerMap.get(clazz.getSuperclass()); }

Notes

  • The fix is backward-compatible: Java enum constants with a body still trigger isAnonymousClass() == true and are handled correctly by the original path.
  • clazz.getSuperclass().isEnum() is the reliable cross-language indicator that clazz is a direct subclass of an enum (i.e., an enum constant body class).

…batis#3658)

In Kotlin, enum constants with overridden abstract methods generate a subclass
where isAnonymousClass() returns false (unlike Java). This caused TypeHandlerRegistry
to fail finding the correct TypeHandler for such enum constants.

Fix by additionally checking clazz.getSuperclass().isEnum() as a fallback
to detect Kotlin-style enum constant subclasses in both getSmartHandler and getJdbcHandlerMap.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug Report: Kotlin anonymous enum constants fail to be recognized in TypeHandlerRegistry

1 participant