有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何在java/kotlin中使用注释处理将方法附加到现有类中?

我不熟悉注释处理和代码生成。我想知道如何执行这样的操作,比如将新方法附加到现有类中。下面是我想做的一个例子:

假设我们有一个带有如下自定义注释的类:

class SourceClass {
    @CustomAnnotation
    fun annotatedFun1(vararg argument: Any) {
        //Do something
    }

    @CustomAnnotation
    fun annotatedFun2(vararg argument: Any) {
        //Do something
    }

    fun someOtherFun() {
        //Do something
    }
}

我想得到的结果是——该类的扩展副本:

class ResultClass {
    fun hasFunWithName(name: String): Boolean {
        return (name in arrayOf("annotatedFun1", "annotatedFun2"))
    }

    fun callFunByName(name: String, vararg arguments: Any) {
        when (name) {
            "annotatedFun1" -> annotatedFun1(*arguments)
            "annotatedFun2" -> annotatedFun2(*arguments)
        }
    }

    fun annotatedFun1(vararg argument: Any) {
        //Do something
    }

    fun annotatedFun2(vararg argument: Any) {
        //Do something
    }

    fun someOtherFun() {
        //Do something
    }
}

我已经了解了如何创建注释处理器。我正在寻找一种方法来保存源类中所有现有的字段、属性和方法,并在其中附加一些方法

如果可以在不创建新类的情况下修改类,那就太完美了,但在所有教程中,只创建了新类,而且我没有发现任何将源类的所有内容复制到另一个类的示例

请不要建议使用反射。我需要安卓的这个,所以反射不是资源成本的原因。我正在寻找编译时解决方案

它是应用程序中实现的自定义脚本语言所必需的,应该用于简化包装类结构。当这项工作直接在代码中完成时——当这样的方法计数超过每个类20个时,看起来很糟糕


共 (3) 个答案

  1. # 2 楼答案

    下面是我最近使用的Java注释处理的good example。 这是an implementation@Immutable注释

    查看ByteBuddy或Kotlin Poet,了解额外代码生成的工作原理

    对于Kotlin,您可以执行几乎相同的操作,检查this manual以了解Kotlin的具体步骤

  2. # 3 楼答案

    你可能会遵循Project Lombok所使用的模式。详见How does lombok work?source code

    另一种选择是编写一个扩展源类的新类:

    class ResultClass : SourceClass {
        fun hasFunWithName(name: String): Boolean {
            return (name in arrayOf("annotatedFun1", "annotatedFun2"))
        }
    
        fun callFunByName(name: String, vararg arguments: Any) {
            when (name) {
                "annotatedFun1" -> annotatedFun1(*arguments)
                "annotatedFun2" -> annotatedFun2(*arguments)
            }
        }
    }
    

    或者可以使用composition代替,并对SourceClass中的所有公共方法使用implementcover方法

    如果您不想使用注释处理来实现这一点,那么可以在编译之前使用一段单独的自定义代码来处理源代码文件。可以使用/@CustomAnnotation\s+.*fun (\w+)\s*\(([^)]*)\)/gmTest on Regex101)这样的正则表达式来查找带注释的方法