import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value();
int[] numbers();
}
This creates an annotation called MyAnnotation
that can be applied to methods. The annotation has two properties: value
(a string) and numbers
(an array of integers). The @Retention
annotation specifies that the annotation should be retained at runtime, and the @Target
annotation specifies that the annotation can only be applied to methods.
public class MyClass {
@MyAnnotation(value = "hello", numbers = {1, 2, 3})
public void myMethod() {
// method body
}
}
In this example, MyAnnotation
is applied to the myMethod()
method with a value of "hello" and an array of numbers [1, 2, 3]. You can access the values of the annotation at runtime using reflection:
MyAnnotation annotation = MyClass.class.getMethod("myMethod").getAnnotation(MyAnnotation.class);
System.out.println(annotation.value()); // prints "hello"
System.out.println(Arrays.toString(annotation.numbers())); // prints "[1, 2, 3]"
This code retrieves the MyAnnotation
annotation from the myMethod()
method of the MyClass
class and prints its value
and numbers
properties.
You can also create a custom annotation processor to generate code based on your annotations. Here's an example:
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.tools.*;
import java.io.*;
import java.util.*;
@SupportedAnnotationTypes("MyAnnotation")
public class MyAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
String value = annotation.value();
int[] numbers = annotation.numbers();
String methodName = element.getSimpleName().toString();
String generatedClassName = methodName + "Generated";
String generatedClassContent = "public class " + generatedClassName + " {\n";
generatedClassContent += " public static void main(String[] args) {\n";
generatedClassContent += " System.out.println(\"" + value + "\");\n";
generatedClassContent += " System.out.println(Arrays.toString(new int[] {" + Arrays.toString(numbers).replaceAll("\\[|\\]", "") + "}));\n";
generatedClassContent += " }\n";
generatedClassContent += "}\n";
try {
JavaFileObject javaFileObject = processingEnv.getFiler().createSourceFile(generatedClassName);
Writer writer = javaFileObject.openWriter();
writer.write(generatedClassContent);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
}
This annotation processor generates a new Java class for each method annotated with MyAnnotation
. The generated class simply prints the value
and numbers
properties of the annotation. To use this annotation processor, you need to create a file called javax.annotation.processing.Processor
in the META-INF/services
directory of your project, containing the fully qualified name of your annotation processor:
com.example.MyAnnotationProcessor
When you compile your project, the annotation processor will automatically generate the necessary code for each method annotated with MyAnnotation
.
To use the MyAnnotationProcessor
, you would typically compile your Java code with the -processor
option, like this:
javac -processor com.example.MyAnnotationProcessor MyClass.java
This will run the MyAnnotationProcessor
on the MyClass
file and generate the necessary code.
Keep in mind that this is just a simple example to demonstrate how annotations and annotation processors work in Java. In real-world scenarios, you would typically use annotations and annotation processors to generate more complex code, such as code for dependency injection or serialization.