2012-03-13 39 views
5

Tôi có vấn đề nhỏ. Tôi học java SE và tìm ClassLoader lớp. Tôi cố gắng sử dụng nó trong mã dưới đây: Tôi đang cố gắng sử dụng URLClassLoader để nạp động một lớp vào thời gian chạy.Ví dụ Java với ClassLoader

URLClassLoader urlcl = new URLClassLoader(new URL[] {new URL("file:///I:/Studia/PW/Sem6/_repozytorium/workspace/Test/testJavaLoader.jar")}); 
Class<?> classS = urlcl.loadClass("michal.collection.Stack"); 
for(Method field: classS.getMethods()) { 
    System.out.println(field.getName()); 
} 
Object object = classS.newInstance(); 
michal.collection.Stack new_name = (michal.collection.Stack) object; 

Các máy ảo java không thấy tôi lớp, và tôi nhận được ngoại lệ sau đây:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: michal cannot be resolved to a type michal cannot be resolved to a type at Main.main(Main.java:62) 

Bạn có biết làm thế nào tôi có thể giải quyết vấn đề này?

+0

bạn có thể đăng ngoại lệ và theo dõi ngăn xếp mà bạn nhận được không? – Shaunak

+0

Dĩ nhiên: Exception in thread "main" java.lang.Error: vấn đề biên soạn Chưa giải quyết: \t Michal không thể giải quyết cho một loại \t Michal không thể giải quyết cho một loại \t tại Main.main (Main.java: 62) –

Trả lời

4
Class<?> classS = urlcl.loadClass("michal.collection.Stack"); 
[...] 
Object object = classS.newInstance(); 
michal.collection.Stack new_name = (michal.collection.Stack) object; 

Vì vậy, bạn đang cố tải động một lớp và sau đó bạn tham chiếu tĩnh vào lớp đó. Nếu bạn đã có thể liên kết tĩnh với nó, sau đó nó được tải và bạn không thể tải lại nó. Bạn sẽ cần phải truy cập các phương thức bằng cách phản ánh.

Điều bạn thường làm là yêu cầu lớp được tải triển khai giao diện từ trình nạp lớp cha. Sau khi một cá thể được tạo ra (thường chỉ là một cá thể), thì bạn có thể tham chiếu đến nó thông qua một tham chiếu với một kiểu giao diện.

public interface Stack { 
    [...] 
} 
[...] 
    URLClassLoader urlcl = URLClassLoader.newInstance(new URL[] { 
     new URL(
      "file:///I:/Studia/PW/Sem6/_repozytorium/workspace/Test/testJavaLoader.jar" 
     ) 
    }); 
    Class<?> clazz = urlcl.loadClass("michal.collection.StackImpl"); 
    Class<? extends Stack> stackClass = clazz.asSubclass(Stack.class); 
    Constructor<? extends Stack> ctor = stackClass.getConstructor(); 
    Stack stack = ctor.newInstance(); 

(thông thường Stack Overflow từ chối trách nhiệm về việc không quá nhiều như biên soạn.)

Bạn sẽ cần phải thêm xử lý nếm lỗi. URLClassLoader.newInstance thêm một chút sàng lọc vào URLClassLoader. Class.newInstance đã hoàn toàn bị xử lý ngoại lệ và nên tránh.

+0

Vậy làm thế nào tôi có thể sử dụng phương pháp từ lớp này? –

+0

@ user1267483 Bạn sẽ cần phải tạo một giao diện trong dự án mà bạn đang sử dụng URLClassloader cho Stack, mà michal.collection.Stack của bạn thực hiện. –

+0

@ user1267483 Lưu ý, tôi đã thay đổi tên của 'Stack' thành' StackImpl' (không phải là tên tốt nhất, nhưng thông thường), và giới thiệu một giao diện mới, 'Stack'. –

0

Bạn không thể tham chiếu đến loại được tải động theo tên trong mã, vì điều đó phải được giải quyết tại thời gian biên dịch. Bạn sẽ cần phải sử dụng chức năng newInstance() của đối tượng Class bạn nhận được từ loadClass().

+1

OP đang sử dụng 'Class.newInstance' trên đối tượng' Class' từ 'loadClass'. –

0

Các câu trả lời ở trên đều sai, họ không hiểu vấn đề gốc. Mục chính của bạn là lớp Stack được nạp bởi một trình nạp lớp. Trình tạo lớp url của bạn đang cố tải một lớp có cùng tên. Bạn không thể truyền tải được nạp vào bởi vì chúng không giống nhau, chúng thuộc về các trình nạp lớp khác nhau. Bạn có thể in mã có của mỗi mã để xem chúng khác nhau. Một kiểm tra bình đẳng cũng sẽ hiển thị các tham chiếu cclass là khác nhau. Vấn đề của bạn có lẽ là do các lớp phụ thuộc được tham chiếu bởi sstack có thể được tìm thấy, nó sẽ trả về trong NoClassDefErrors vv. Chính bạn có lẽ sẽ thất bại với một nhận dạng lớp.