반사를 사용하여 private static final
필드의 값을 변경하려고했습니다 (예, 처음에는 매우 나쁜 생각이었습니다). 예상대로 인쇄Java Reflection - "get"작업 앞에 "set"이있는 경우 IllegalAccessException
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class A {
public static void main(String[] args) throws ReflectiveOperationException {
System.out.println("Before :: " + B.get());
Field field = B.class.getDeclaredField("arr");
field.setAccessible(true);
// System.out.println("Peek :: " + ((String[]) field.get(null))[0]);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, new String[] { "Good bye, World!" });
System.out.println("After :: " + B.get());
}
}
class B {
private static final String[] arr = new String[] { "Hello, World!" };
public static String get() {
return arr[0];
}
}
: 다음 코드 그리고, 물론, 대부분의 경우는 잘 사용하여 작동 내가 반사를 통해 get
로 필드 값을하려고 할 때
Before :: Hello, World!
After :: Good bye, World!
문제가 발생 이전에 set
팅. 나는 위의 예제에서 주석 행의 주석을 해제하면, 나는 다음과 같은 수 있습니다 :
Before :: Hello, World!
Peek :: Hello, World!
Exception in thread "main" java.lang.IllegalAccessException: Can not set static final [Ljava.lang.String; field B.arr to [Ljava.lang.String;
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.set(UnsafeQualifiedStaticObjectFieldAccessorImpl.java:77)
at java.lang.reflect.Field.set(Field.java:764)
at A.main(A.java:14)
왜 이런 일이? get
을 호출 한 후 accessible
플래그를 다시 설정하려고 시도했지만 도움이되지 않습니다. 나는 도움이되지 않는 많은 다른 것들을 시도했다 ...
당신의 도움에 감사드립니다!
편집는 (@ ROGERIO에 의해 참조 "중요 업데이트") Using reflection to change static final File.separatorChar for unit testing? 답변의 요소가있다.
중요 업데이트 : 모든 경우에하지 작업을 수행 위의 솔루션입니다. 필드가 액세스 가능 해지고 Reflection을 통해 읽혀 재설정되기 전에 읽으면
IllegalAccessException
이 발생합니다. Reflection API가 캐시되고 재사용되는 내부FieldAccessor
오브젝트를 작성하기 때문에 실패합니다 (java.lang.reflect.Field # acquireFieldAccessor (boolean) 구현 참조). 실패 예제 테스트 코드 :Field f = File.class.getField("separatorChar"); f.setAccessible(true); f.get(null); // call setFinalStatic as before: throws IllegalAccessException
을 슬프게도, 그것을 해결하는 방법에 대해 아무 말도하지 않고는 ... 어떻게 필드를 "재설정"합니까?
최종적으로 설정할 수 없습니다. –
흥미롭게도, 리플렉션을 통해 정상적인 방법으로 값을 얻는다면 나중에 리플렉션을 통해 설정하면 오류가 발생하지 않습니다. –
흥미로운 질문입니다. 이 코드가 어디에서 왔는지 보려면 코드를 살펴보십시오. – Marco13