Ładowanie klasy z jara w czasie działania programu

Ładowanie klasy z jara w czasie działania programu
Wizzie
  • Rejestracja: dni
  • Ostatnio: dni
0

Próbuję napisać funkcję, który zeskanuje jara, pobierze z niego klasę o nazwie ***CommandExecutor i zwróci obiekt tej klasy. Klasę pobrałem, ale nie potrafię sobie poradzić ze stworzeniem instancji tej klasy. W tym końcowym try'u wszystko błyska czerwonością, to tylko raczej próba pokazanie mojego procesu myślowego.

Kopiuj
 private CommandExecutor parseCommand(Path filePath) {
        String path = filePath.toString();
        JarFile jar = null;
        URL[] urls = null;
        try {
            jar = new JarFile(path);
            urls = new URL[]{ new URL("jar:file:" + path + "!/")};
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(jar == null || urls == null)
            return null;

        URLClassLoader classLoader = new URLClassLoader(urls);

        Enumeration<JarEntry> entries = jar.entries();
        while(entries.hasMoreElements()){
            JarEntry entry = entries.nextElement();
            if(entry.getName().contains("CommandExecutor.class")){
                String className = entry.getName().substring(0,entry.getName().length()-6); // -6 because of .class
                try {
                    Class<CommandExecutor> clazz = classLoader.loadClass(className);
                    Constructor<clazz> constructor = clazz.getConstructor();
                    CommandExecutor executor = constructor.newInstance();
                    return executor;
                } catch (NoSuchMethodException | ClassNotFoundException
                        | InstantiationException | InvocationTargetException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

CommandExecutor to interfejs.

Błędy:

Kopiuj
Error:(90, 73) java: incompatible types: java.lang.Class<capture#1 of ?> cannot be converted to java.lang.Class<me.wizziee.pilot.common.CommandExecutor>
  • dla pierwszej linijki w try'u
Kopiuj
Error:(91, 33) java: cannot find symbol
  symbol:   class clazz
  location: class me.wizziee.pilotserver.Server
  • dla drugiej linijki w try'u
Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1
Kopiuj
Class<CommandExecutor> clazz = classLoader.loadClass(className);

Tak ci nie wolno bo loadClass zwraca Class<?> i już. Jest tak dlatego że w javie generici są tylko na poziomie kodu źródłowego, w runtime już nie (przynajmniej teoretycznie).
2.

Kopiuj
Constructor<clazz> constructor = clazz.getConstructor();

Zgodnie z powyższym, nie ma to sensu. Bo twoje clazz będzie znane dopiero na etapie działania a nie kompilacji.

Wizzie
  • Rejestracja: dni
  • Ostatnio: dni
1

Ok, to co próbowałem robić to rzutowanie na typ nieznany w czasie kompilacji, co jest chyba niemożliwe (w końcu to język statycznie typowany). newInstance() zwraca Object, więc wystarczy rzutować na interfejs:

Kopiuj
Class clazz = classLoader.loadClass(className);
CommandExecutor executor = (CommandExecutor)clazz.newInstance();

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.