Up to this point, you’ve seen many features for working with classes and functions, but they all require you to specify the exact names of classes and functions you’re using as part of the program source code. To call a function, you need to know the class in which it was defined as well as its name and parameter types. Annotations and reflection give you the power to go beyond that and to write code that deals with arbitrary classes that aren’t known in advance. You can use annotations to add additional metadata and semantics to declarations. For example, you could use them to indicate whether a declaration is deprecated (as you’ll see in section 12.1.1), you could use them for integrations with the compiler, your IDE, and external tools (as you’ll see in section 12.1.2), or you could use them to construct library-specific and custom semantics. Reflection allows you to analyze your declarations at run time.
Applying annotations is straightforward, but writing your own annotations, and especially writing the code that handles them, is less trivial. The syntax for using annotations is exactly the same as in Java, whereas the syntax for declaring your own annotation classes is a bit different. The general structure of the reflection APIs is also similar to Java, but the details differ.