Khi tôi chạy mã Java sau:Các ClassLoader có thể thay thế mảng bởi bất cứ điều gì
ClassLoader c = new ClassLoader() {
@Override
public Class<?> findClass(String name) {
return Object.class;
}
};
Class<?> cc = c.loadClass(Object[][].class.getName());
System.out.println(cc.getName());
tôi nhận được java.lang.Object
tại nhà ga hiển thị, ngay cả khi tôi thay Object[][].class.getName()
bởi [[Ljava.lang.Object
trong các mã. Vấn đề là tôi đã mong đợi giao diện điều khiển hiển thị [[Ljava.lang.Object
.
Trong thực tế, trong JVM specification, tôi có thể đọc phần sau đây:
Một lớp mảng được tạo ra trực tiếp bởi Java Virtual Machine (§5.3.3), chứ không phải bởi một bộ nạp lớp. Tuy nhiên, lớp định loader của D được sử dụng trong quá trình tạo mảng lớp C.
Kể từ Object[][]
là một lớp mảng, tôi cho rằng findClass
của tôi sẽ không được gọi với đối số [[Ljava.lang.Object
nhưng với yếu tố của nó nhập java.lang.Object
.
Hơn nữa, trong phần "Tạo lớp Array", thuật toán đệ quy là thực sự mô tả:
Nếu loại thành phần là một loại tài liệu tham khảo, thuật toán của phần này (§5.3) được áp dụng một cách đệ quy sử dụng lớp loader L để tải và do đó tạo ra các kiểu thành phần của C.
Vì vậy, câu hỏi của tôi là:
- tại sao tôi nhận outp này ut? Nó có nghĩa là tôi phải tự bao gồm thuật toán đệ quy này bên trong ClassLoader của tôi, thay vì để JVM làm việc đó cho tôi? Nếu đây là ý nghĩa của nó, cách tốt nhất để làm điều đó là gì?
- Tôi có hiểu sai về "được tạo" trong báo giá đầu tiên không? Liệu nó chỉ có nghĩa là tôi không thể tạo ra các lớp mảng thời gian chạy, nhưng tôi vẫn có thể vá tải của nó?
Điểm OP là spec có vẻ chỉ ra rằng trong trường hợp các lớp mảng, JVM tránh sử dụng trình nạp lớp và nạp trực tiếp lớp đó. Và đây là một câu hỏi rất hay. –
Có, tôi đã làm điều này có mục đích để vá tải của loại phần tử của mảng (chỉ để kiểm tra). Nhưng thay vào đó, nó thay thế toàn bộ mảng. – Codoscope