2009-08-23 16 views
6

Jest to kontynuacja pytanie odpowiedział: How to load a jar file at runtimeW jaki sposób uzyskuje się dostęp do metody z zewnętrznego słoika w środowisku wykonawczym?

Jestem niepewna, jak kontynuować do poziomu wywołania metody. Z mojego zrozumienia, z obiektu clazz, użyłbym getMethod lub getDeclaredMethod, aby uzyskać obiekt Method, z którego wywołałbym wywołanie. Oczywiście wywołanie wymaga instancji. Czyżby to było, co nazywa się doRun w przykładowym kodzie?

Czy muszę wykonać wywołanie metody doRun.run(), mimo że chcę wykonać inną metodę niż główna (zakładając, że jest ona głównym obiektem doRun wywoływanym przy wywołaniu uruchamiania)?

Po prostu dla wyjaśnienia pierwotnego postu, pytam: Czy doRun.run() uruchamia nowy wątek wykonujący wystąpienie klasy obiektu clazz?

Dzięki za pomoc w wyjaśnieniu tego dla mnie.

Spojrzałem na "how-should-i-load-jars-dynamically-at-runtime" (przepraszam, dozwolone jest tylko jedno hiperłącze), jednak to wyglądało na naruszanie napomnienia klasowego Class.newInstance w pierwszym poście. wymienione.

Odpowiedz

2

Oto kod refleksja, że ​​nie rzuca do interfejsu:

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); 
    } 
} 

Pisanie odbite klas do interfejsu znanego kod konsumenta (as in the example) jest ogólnie lepszy, ponieważ pozwala uniknąć refleksji i skorzystać z systemu typu Java. Refleksji należy używać tylko wtedy, gdy nie masz wyboru.

+0

Tak więc, jeśli rozumiem twój komentarz po kodzie, z interfejsem, wiem jakie metody są dostępne i mogę napisać kod wywołujący metodę bezpośrednio po odpowiednim rzuceniu obiektu instancji. Czy to prawda? – Todd

+0

Oczywiście zakłada się, że oryginalny kod został skompilowany przy użyciu interfejsu, a nie taki, który utworzę później i spróbuję rzucić to wystąpienie. – Todd

+0

@Todd - tak, masz to. Interfejs (lub jakaś inna implementacja typu silnego) jest często używany z wtyczkami, w których kod został napisany do dynamicznego tworzenia. Jeśli wykonujesz introspekcję i wywołanie na dowolnych klasach, nie jest to opcja. – McDowell

2

Przykładowy kod

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(); 

zakłada, że ​​klasa ładowanego implementuje dany interfejs Runnable, a zatem jest to reasonale rzucić do tego typu przy użyciu asSubclass() i wywołać run().

Co wiesz o ładowaniu zajęć? Czy możesz założyć, że implementują interfejs particualr? Jeśli tak, dostosuj linię asSubClass(), aby odwołać się do preferowanej interfazy.

Następnie, jeśli pracujesz z metodami instancji, stwórz instancję za pomocą contruktora, ctor w tym przykładzie.

W tym przykładzie nie ma początku wątku. Tworzenie nowego wątku byłoby po prostu potrzebowałem paru liniach więcej kodu

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

djna - dzięki za odpowiedź. Niestety, nie mogę założyć, że wiem cokolwiek o klasach, które mogę ładować. Mam jeden przykładowy przypadek, który może nie wskazywać na wykorzystanie w realnym świecie. W obecnej postaci nie podklasuję, nie pobieram instancji od konstruktora, a następnie kontynuuję korzystanie z getDeclaredMethod, podobnie do postu poniżej. Dzięki za inne wyjaśnienie, byłem zdezorientowany z powodu inwokacji biegu, myślałem, że oznacza to początek nowego wątku - mój zły. – Todd

1

Przykładowy program:

Drukarka Projekt:

public class Printer { 

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

} 

Ten projekt jest eksportowany jako Printer.jar.

Klasa drukarki ma metodę display(), która przyjmuje ciąg jako dane wejściowe.

Wywoływanie kodu:

 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(); 

wyjściowa: Print this

Powiązane problemy