Also, java annotation processors are strictly "append-only", they can't change code written as is. They may subclass it, or build new classes that make use of the annotations.
In my experience LLMs are more than happy with annotations, especially from the widely used ones (spring/jakarta ee, lombok though it's not an annotation processor, etc).
If you think about it, an annotation like @Path("/endpoint") is very informative for both humans and LLMs alike, being local to what it attaches to. Within an agent, the code serving the endpoint will be immediately visible in the context returned by a simple string search, no need to do another round of "find wherever this codebase registers routes".
Go has no such things and you have circled back exactly to the GP's point: "There's a ceiling on abstraction". There is no such ceiling in java ime
There is no case where annotations are superior to the meta programming facilities built into the language proper. Annotations only became popular because Java didn’t have easy syntax for function references or anonymous functions for a very long time.
Also, hard disagree on "register" method being simpler. A register method is code, while an annotation is a static declaration, ergo data. The former can happen in a helper function, renaming it from "register" to "path", changing/modifying the parameters, or putting it into some while loop dynamically generating endpoints.
At the very extreme it is Turing complete to figure out what endpoints are registered.
The annotations are static, yeah. That's one advantage. I would still rather not do that. A lot of people were happy not to need that anymore in like NodeJS.
And old code continuing to run 10 years later is a huge value of the platform.
Mostly old code will keep working, but there are exceptions like Python 2->3 breakage that deserves all the criticism it got.
Code is data.
Data is code.
Biggest thing was lack of cooperative multitasking until virtual threads (Project Loom). And much older, lack of lambdas before Java 8.