2009-08-23 39 views
6

Đây là sự tiếp nối của câu hỏi được đăng trong: How to load a jar file at runtimeLàm cách nào để truy cập một phương thức từ một bình bên ngoài khi chạy?

Tôi không chắc chắn về cách tiếp tục với cấp độ yêu cầu phương thức. Từ sự hiểu biết của tôi, từ đối tượng clazz, tôi sẽ sử dụng getMethod hoặc getDeclaredMethod để có được một đối tượng Method mà từ đó tôi sẽ gọi invoke. Tất nhiên, gọi đòi hỏi một thể hiện. Điều đó có được gọi là doRun trong mã ví dụ không?

Tôi có cần thực hiện cuộc gọi phương thức doRun.run() ngay cả khi tôi muốn thực thi một phương thức khác với chính (giả sử rằng nó là chính trên đối tượng doRun được gọi với lời gọi chạy)?

Chỉ cần làm rõ thêm bài đăng gốc, tôi hỏi: DoRun.run() có bắt đầu một chuỗi mới thực thi cá thể của đối tượng lớp kiểu clazz không?

Cảm ơn bạn đã giúp tôi xóa nội dung này.

Tôi đã xem xét "làm thế nào-nên-i-load-jars-động-tại-thời gian chạy" (xin lỗi, chỉ cho phép một siêu liên kết), tuy nhiên điều này có vẻ vi phạm các lời than phiền Class.newInstance ác trong bài đầu tiên tôi được tham chiếu.

Trả lời

2

Dưới đây là một số mã phản ánh rằng không cast đến một giao diện:

public class ReflectionDemo { 

    public void print(String str, int value) { 
    System.out.println(str); 
    System.out.println(value); 
    } 

    public static int getNumber() { return 42; } 

    public static void main(String[] args) throws Exception { 
    Class<?> clazz = ReflectionDemo.class; 
    // static call 
    Method getNumber = clazz.getMethod("getNumber"); 
    int i = (Integer) getNumber.invoke(null /* static */); 
    // instance call 
    Constructor<?> ctor = clazz.getConstructor(); 
    Object instance = ctor.newInstance(); 
    Method print = clazz.getMethod("print", String.class, Integer.TYPE); 
    print.invoke(instance, "Hello, World!", i); 
    } 
} 

Viết các lớp phản ánh với một giao diện được biết đến bởi mã người tiêu dùng (as in the example) nói chung là tốt hơn vì nó cho phép bạn tránh phản ánh và tận dụng lợi thế của hệ thống kiểu Java. Phản ánh chỉ nên được sử dụng khi bạn không có lựa chọn.

+0

Vì vậy, nếu tôi hiểu nhận xét của bạn theo mã, với giao diện, tôi biết phương thức nào có sẵn và có thể viết mã gọi phương thức trực tiếp sau khi truyền đối tượng mẫu một cách thích hợp. Điều này có đúng không? – Todd

+0

Tất nhiên, giả định rằng mã ban đầu đã được biên dịch bằng cách sử dụng giao diện, không phải là một trong những tôi tạo ra sau này và cố gắng để đúc dụ. – Todd

+0

@Todd - vâng, bạn đã có nó. Cách tiếp cận giao diện (hoặc một số kiểu triển khai mạnh) khác thường được sử dụng với các trình bổ sung nơi mã được viết để được khởi tạo động. Nếu bạn đang làm nội tâm và yêu cầu trên các lớp tùy ý, đây không phải là một tùy chọn. – McDowell

2

Đoạn mã ví dụ

ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL }, 
    getClass().getClassLoader() 
); 
Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class); 
// Avoid Class.newInstance, for it is evil. 
Constructor<? extends Runnable> ctor = runClass.getConstructor(); 
Runnable doRun = ctor.newInstance(); 
doRun.run(); 

giả định rằng các lớp học mà bạn đang tải thực hiện một giao diện cụ thể Runnable, và do đó nó là cả hợp lý để cast để loại rằng việc sử dụng asSubclass() và gọi run().

Bạn biết gì về các lớp bạn đang tải? Bạn có thể giả định rằng họ thực hiện một giao diện particualr? Nếu điều chỉnh dòng asSubClass() để tham chiếu đến interafce bạn thích.

Sau đó, có nếu bạn đang làm việc với các phương pháp ví dụ tạo một thể hiện bằng cách sử dụng contructor, ctor trong ví dụ.

Không có bắt đầu chuỗi trong ví dụ. Tạo một chủ đề mới sẽ chỉ có cần một vài dòng mã hơn

Thread myThread = new Thread(doRun); 
myThread.start(); 
+0

djna - cảm ơn cho câu trả lời. Thật không may, tôi không thể giả định rằng tôi biết bất cứ điều gì về các lớp học mà tôi có thể đang tải. Tôi có một trường hợp mẫu có thể không mang tính biểu thị của việc sử dụng thế giới thực. Vì nó là viết tắt, tôi không phân lớp, có được một thể hiện từ các nhà xây dựng, sau đó tiến hành bằng cách sử dụng getDeclaredMethod, tương tự như bài viết dưới đây. Cảm ơn cho việc làm rõ khác, tôi đã nhầm lẫn về cuộc gọi chạy, nghĩ rằng có nghĩa là một chủ đề mới là để bắt đầu - xấu của tôi. – Todd

1

Chương trình mẫu:

Dự án Máy in:

public class Printer { 

    public void display(String printtext) 
    { 
     System.out.println(printtext); 
    } 

} 

Dự án này được xuất khẩu như Printer.jar.

Lớp máy in có phương thức display() lấy chuỗi làm đầu vào.

đang Gọi:

 URL url = new URL("file:Printer.jar"); 
     URLClassLoader loader = new URLClassLoader (new URL[] {url}); 
     Class<?> cl = Class.forName ("Printer", true, loader); 
     String printString = "Print this"; 
     Method printit = cl.getMethod("display", String.class); 
     Constructor<?> ctor = cl.getConstructor(); //One has to pass arguments if constructor takes input arguments. 
     Object instance = ctor.newInstance(); 
     printit.invoke(instance, printString); 
     loader.close(); 

Output: Print this

Các vấn đề liên quan