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?
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.
Mutation is basically changing the array itself instead of returning a new array with the new changes.
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.
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.
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With