Search code examples
javaarraysannotationsimmutability

How do annotations prevent mutations of an array parameter?


I understand that annotations are immutable, however, arrays in Java are by themselves not immutable. After running a test I notice that the array returned from an annotation parameter can be mutated but it does not effect the source array:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface ArrayAnnotation {
    String[] value() default {};
}

@ArrayAnnotation({"foo"})
public class Main {
    public static void main(String[] args) {
        ArrayAnnotation test = Main.class.getAnnotation(ArrayAnnotation.class);

        String[] test0 = test.value();
        test0[0] = "bar";
        System.out.println(test0[0]);

        String[] test1 = test.value();
        System.out.println(test1[0]);
    }
}

This prints:

bar
foo

What is going on behind the scenes here? Is there simply an array copy happening during each call to value(), or is it something more complex?


Solution

  • Is there simply an array copy happening during each call to value(), or is it something more complex?

    Yes, the array is copied.


    Annotations are a special kind of interface type. (JLS)

    They are implemented by some Proxy classes at runtime. You can debug it if you set breakpoint at Proxy.newProxyInstance().

    Invocations on annotation are intercepted by AnnotationInvocationHandler which copies arrays:

    if (result.getClass().isArray() && Array.getLength(result) != 0)
         result = cloneArray(result);