1

There is something wrong in my setup, but i can't figure out what it is. From Kotlin compiler plugins i have following information.

The no-arg compiler plugin generates an additional zero-argument constructor for classes with a specific annotation.

The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.

That said, i would think i could access the noarg constructor by both java and kotlin reflection, but i can only access it by java reflection. Is this the intended behaviour, or am i doing something wrong?

build.gradle

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.50'
    id "org.jetbrains.kotlin.plugin.noarg" version "1.3.50"
    id 'application'
    id 'java'
}

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.3.50'
}

noArg {
    annotation('noargdemo.Entity')
}

application {
    mainClassName = 'noargdemo.AppKt'
}
package noargdemo

import kotlin.reflect.full.createInstance

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Entity

@Entity
data class Employee(
        val firstName : String,
        val secondName : String
)

fun main(args: Array<String>) {
    val kotlinConstructors = Employee::class.constructors // size is 1
    val javaConstructors = Employee::class.java.constructors // size is 2
    val instance1 = Employee::class.java.getConstructor().newInstance() // works
    val instance2 = Employee::class.createInstance() // doesnt work
}
1
  • 1
    it's right in the thing you quoted: The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection. Commented Nov 22, 2019 at 11:32

1 Answer 1

2

This is intended behaviour, it's stated even in that description your quoted:

The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.

Synthetic methods are methods generated by the compiler for internal purposes, they can't be called manually from source code but they are visible for reflections.

You can check if method is synthetic by using Method.isSynthetic: https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isSynthetic--

Sign up to request clarification or add additional context in comments.

4 Comments

alright, but why can't i access it by kotlin's reflection?
@mesinger it is kotlin reflection API, it shows you kotlin code elements, and this constructor is not part of your kotlin code. kinda like you can't find information about kotlin default parameters from java reflections bue kotlin reflection gives you that. But I will try to check for more, as you might argue that description states it should be there, so I will try to find more information on this
The documentation is definetly misleading, if it states it is available via reflection, but only available via java's reflection.
You said, Java reflections can't find information about kotlin default params. Well, of course Java reflection doesn't know about default params, because it doesn't know about Kotlin in the first place. Kotlin on the other hand knows about java, and as my example shows, Kotlin reflect could provide synthetic functions as well. It would be nice to know, why they chose not to do that, as it could create even weirder problems, e.g. when you work on java code annotated with lombok.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.