Tôi gặp phải hành vi lạ khi cố gắng ghi đè phương thức với accessor mặc định (ví dụ: void run()
). Theo đặc tả Java, một lớp có thể sử dụng hoặc ghi đè lên các thành viên mặc định của lớp cơ sở nếu các lớp thuộc cùng một gói. Mọi thứ hoạt động chính xác trong khi tất cả các lớp được nạp từ cùng một trình nạp lớp. Nhưng nếu tôi cố gắng tải một lớp con từ riêng biệt trình nạp lớp thì tính đa hình sẽ không hoạt động.Ghi đè phương thức truy cập mặc định trên các trình nạp lớp khác nhau phá vỡ đa hình
Đây là mẫu:
App.java:
import java.net.*;
import java.lang.reflect.Method;
public class App {
public static class Base {
void run() {
System.out.println("error");
}
}
public static class Inside extends Base {
@Override
void run() {
System.out.println("ok. inside");
}
}
public static void main(String[] args) throws Exception {
{
Base p = (Base) Class.forName(Inside.class.getName()).newInstance();
System.out.println(p.getClass());
p.run();
} {
// path to Outside.class
URL[] url = { new URL("file:/home/mart/workspace6/test2/bin/") };
URLClassLoader ucl = URLClassLoader.newInstance(url);
final Base p = (Base) ucl.loadClass("Outside").newInstance();
System.out.println(p.getClass());
p.run();
// try reflection
Method m = p.getClass().getDeclaredMethod("run");
m.setAccessible(true);
m.invoke(p);
}
}
}
Outside.java: phải ở trong thư mục riêng biệt. khác classloader sẽ giống nhau
public class Outside extends App.Base {
@Override
void run() {
System.out.println("ok. outside");
}
}
Sản lượng:
class App$Inside
ok. inside
class Outside
error
ok. outside
Vì vậy, sau đó tôi gọi Outside#run()
tôi đã Base#run()
("lỗi" trong đầu ra). Reflections hoạt động chính xác.
Có gì không ổn? Hay là hành vi mong đợi? Tôi có thể giải quyết vấn đề này bằng cách nào đó không?
Tôi nhận thấy rằng lớp 'Bên ngoài' của bạn tuyên bố' chạy' là công khai ... Tôi tự hỏi nếu đó là vấn đề. Bạn có thể thử nó với 'Outside.run' có quyền truy cập mặc định không? –
Nếu 'External # run' có accessor mặc định khi Reflections (không có' setAccessible (true) ') _also_ không hoạt động:' 'Exception in thread" main "' java.lang.IllegalAccessException: Class App không thể truy cập vào thành viên class Outside with modifiers "" ' – mart
Tôi viết lại mẫu cho External # run có accessor mặc định – mart