In most cases, I’ve found annotations to be the cause of most runtime exceptions. Don’t get me started with Guice + annotations…
That ignores the entire other half of the annotation world that are compile time only annotations, either useful for javac itself or for doing common things like code generation for JSON encoding/decoding.
The author touches on compile-time annotations briefly, mainly to say that compile-time annotations are rarely used.
For my part, the only compile time annotations I’ve encountered in the wild were things like FreeBuilder/Immutables/etc. and Dagger. There’s an argument to be made that those are also local minima – especially FreeBuilder. Kotlin, Scala and Ceylon have special syntax which solves the problem of writing data classes quickly and correctly at the language level. I’ve found the annotation processing solutions to be a lesser replacement – mostly because of poor integration with all of the existing tooling.
Of course those use cases also make good use of annotations. In practice though, I found those to be siginificantly less used than runtime annotations.