Từ tài liệu cho Field.set
:
Nếu trường cơ bản là cuối cùng, phương pháp ném một IllegalAccessException
trừ setAccessible(true)
đã thành công cho lĩnh vực này và lĩnh vực này là không tĩnh.
Vì vậy, thoạt đầu có vẻ như bạn không may mắn, vì File.separatorChar
là static
. Đáng ngạc nhiên, có là một cách để giải quyết vấn đề này: chỉ cần tạo trường static
không còn là final
thông qua phản ánh.
Tôi thích giải pháp này from javaspecialist.eu:
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
Tôi đã thử nghiệm nó và nó hoạt động:
setFinalStatic(File.class.getField("separatorChar"), '#');
System.out.println(File.separatorChar); // prints "#"
Làm bài tập cực kỳ thận trọng với kỹ thuật này.hậu quả nghiêm trọng sang một bên, sau đây thực sự hoạt động:
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
quan trọng cập nhật: giải pháp trên không làm việc trong mọi trường hợp. Nếu trường này có thể truy cập được và đọc qua Reflection trước khi nó được đặt lại, thì IllegalAccessException
sẽ bị ném. Nó không thành công vì API phản chiếu tạo các đối tượng nội bộ FieldAccessor
được lưu trữ và sử dụng lại (xem triển khai thực hiện java.lang.reflect.Field # obtainFieldAccessor (boolean)). Mã thử nghiệm mẫu không thành công:
Field f = File.class.getField("separatorChar"); f.setAccessible(true); f.get(null);
// call setFinalStatic as before: throws IllegalAccessException
Có thể tốt hơn là chạy thử nghiệm đơn vị trong môi trường VirtualBox trong hệ điều hành đích khác. Ai biết được những gì sẽ phá vỡ khi bạn gây rối với JVM như thế. Ngoài ra, có thể viết lại mã của bạn để không sử dụng trực tiếp File.separatorChar. Bạn có thể xây dựng đường dẫn bằng cách sử dụng hàm tạo tệp (parentFile, name), ví dụ. – Thilo
@ Thilo: Đó là một ý tưởng hay, và bây giờ tôi nghĩ về nó, có lẽ có một cách để chạy logic của tôi theo cách đa nền tảng mà không cần xử lý các URL của tập tin. Tôi nghĩ rằng việc biết cách thay đổi java.io.File.separatorChar, tuy nhiên, là một điều hữu ích để biết về một số trường hợp sử dụng hợp pháp khác. –