注释如何防止数组参数的突变?
How do annotations prevent mutations of an array parameter?
我知道注释是不可变的,但是 Java 中的数组本身并不是不可变的。在 运行 测试后,我注意到从注释参数返回的数组可以改变,但它不会影响源数组:
@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]);
}
}
这会打印:
bar
foo
幕后发生了什么?在每次调用 value()
期间是否只是发生了一个数组复制,还是更复杂的事情?
你说的对,每次returns一份,保证不被改动
在 Java 的未来版本中,可能会优化此副本。
Is there simply an array copy happening during each call to value(), or is it something more complex?
是的,数组被复制了。
注释是一种特殊的 interface
类型。 (JLS)
它们由某些 Proxy
类 在运行时实现。
如果在 Proxy.newProxyInstance()
.
处设置断点,则可以调试它
对注释的调用被 AnnotationInvocationHandler
拦截,它复制数组:
if (result.getClass().isArray() && Array.getLength(result) != 0)
result = cloneArray(result);
我知道注释是不可变的,但是 Java 中的数组本身并不是不可变的。在 运行 测试后,我注意到从注释参数返回的数组可以改变,但它不会影响源数组:
@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]);
}
}
这会打印:
bar
foo
幕后发生了什么?在每次调用 value()
期间是否只是发生了一个数组复制,还是更复杂的事情?
你说的对,每次returns一份,保证不被改动
在 Java 的未来版本中,可能会优化此副本。
Is there simply an array copy happening during each call to value(), or is it something more complex?
是的,数组被复制了。
注释是一种特殊的 interface
类型。 (JLS)
它们由某些 Proxy
类 在运行时实现。
如果在 Proxy.newProxyInstance()
.
对注释的调用被 AnnotationInvocationHandler
拦截,它复制数组:
if (result.getClass().isArray() && Array.getLength(result) != 0)
result = cloneArray(result);