Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 906
flakes Avatar asked Nov 22 '18 18:11

flakes


People also ask

How can an array mutation be prevented?

We can prevent mutation of objects and arrays using the Object. freeze() JavaScript function. We pass the desired object or array as an argument to this function, which later prevents any change to the object's or array's data.

What is mutation in array?

Mutation is basically changing the array itself instead of returning a new array with the new changes.

Is array push a mutation?

Consider a common array mutation: push() . The push() method changes the original array by adding an item to the end. When you add an item, you're mutating the original array. Fortunately, you can avoid the side effect with the spread operator.

What is mutation of data?

A value is said to be mutable if it can be changed. That's all there is to it: a mutation is the act of changing the properties of a value.


2 Answers

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);
like image 112
Denis Zavedeev Avatar answered Sep 22 '22 19:09

Denis Zavedeev


You are right, it returns a copy each time to ensure it is not changed.

In a future version of Java, this copy might be optimised away.

like image 41
Peter Lawrey Avatar answered Sep 22 '22 19:09

Peter Lawrey