简短的回答
这个问题已经有将近 10 年的历史了,但我仍然缺少一个答案。这是:是,但不是因为泛型和注意与 C++ 完全相同。
从 Java 6 开始,我们有 the pluggable annotation processing api。静态元编程是(正如您在问题中已经说过的)
编译时程序执行
如果您了解元编程,那么您也知道这不是真的,但为了简单起见,我们将使用它。如果您想了解有关元编程的更多信息,请查看here。
可插入注解处理 api 由编译器在读取 .java 文件之后但在编译器将字节码写入 .class 文件之前调用。 (我有一个来源,但我再也找不到了。也许有人可以在这里帮助我?)。
它允许您在编译时使用纯 java 代码执行逻辑。然而,你正在编码的世界是完全不同的。不是特别糟糕或什么,只是不同。您正在分析的类尚不存在,您正在处理这些类的元数据。但是编译器是在JVM中运行的,这意味着你也可以正常创建类和程序。但此外,您可以分析泛型,因为我们的注解处理器在 类型擦除之前调用。
关于 java 中静态元编程的主要要点是,您提供元数据(以注释的形式),处理器将能够找到所有带注释的类来处理它们。 (更简单的)示例可以在Baeldung 上找到,其中形成了一个简单的示例。在我看来,这是一个很好的入门资源。如果您了解这一点,请尝试自己google。那里有很多好的资源,这里要列出很多。还可以查看Google AutoService,它利用注释处理器来消除您创建和维护服务文件的麻烦。如果你想创建类,我建议查看JavaPoet。
遗憾的是,这个 API 不允许我们操作源代码。但如果你真的想,你应该看看Project Lombok。他们这样做,但不受支持。
为什么这很重要(感兴趣的人可以继续阅读)
TL;DR:我很困惑,为什么我们不像动态那样使用静态元编程,因为它有很多优点。
大多数开发人员看到“动态和静态”后立即得出结论,即动态更好。没有错,静态对开发人员有很多负面含义。但在这种情况下(特别是对于 java),情况恰恰相反。
动态元编程需要反射,反射有somemajordrawbacks。他们有很多。简而言之:性能、安全性和设计。
静态元编程(即注释处理)允许我们与编译器相交,编译器已经完成了我们尝试通过反射完成的大部分事情。我们还可以在这个过程中创建类,这些类再次传递给注释处理器。然后,您可以(例如)生成类,这些类通常必须使用反射来完成。此外,我们可以实现“快速失败”系统,因为我们可以将错误、警告等通知编译器。
尽可能总结和比较:让我们想象一下春天。 Spring 尝试在运行时查找所有 Component 注释类(我们可以通过在编译时使用服务文件来简化它),然后生成某些代理类(我们已经可以在编译时完成)并解析 bean 依赖项(再次,我们已经可以在编译时完成)。 Jake Whartons talk about Dagger2,他在其中解释了为什么他们切换到静态元编程。我还是不明白为什么像Spring这样的大玩家不使用它。
这篇文章很简短,以充分解释这些差异以及为什么静态会更强大。如果你愿意,我目前正在为此做一个演示。如果您有兴趣并会说德语(对此感到抱歉),您可以查看my website。在那里你会找到一个演示文稿,它试图在 45 分钟内解释这些差异。不过只有幻灯片。