有没有办法转换Class <?将Something>扩展到Class <?>

问题描述

我目前正在开发一个插件,希望在其中创建插件。 因此,我使用ClassLoader,它会检查我插件文件夹中是否有JarFiles,并在其中搜索扩展我的抽象类的类。

现在,我的ClassLoader给我返回了一个带有Class<? extends MyClass>的列表,但是我需要他们成为Class<?>才能执行此类的方法

我已经尝试将其强制转换为Object或自身的类,这给了我ClassCastException。

是否可以将Class<? extends MyClass>转换为Class<?>解决方法

ClassLoader:

public class SPClassLoader {

@SuppressWarnings("unchecked")
public <T> List<Class<? extends T>> findClasses(
        @NonNull final ClassLoader classLoader,@NonNull final File file,@NonNull final Class<T> clazz,@NonNull final Predicate<Class<T>> predicate
) {

    return findClasses(classLoader,file,clazz).stream()
            .filter(aClass -> predicate.test((Class<T>) aClass))
            .collect(Collectors.toList());
}

@SuppressWarnings("unchecked")
public <T> List<Class<? extends T>> findClasses(
        @NonNull final ClassLoader classLoader,@NonNull final Class<T> clazz
) {

    return findClasses(classLoader,clazz::isAssignableFrom).stream()
            .map(aClass -> (Class<T>) aClass.asSubclass(clazz))
            .collect(Collectors.toList());
}

public List<Class<?>> findClasses(
        @NonNull final ClassLoader classLoader,@NonNull final Predicate<Class<?>> predicate
) {

    if (!file.exists()) {
        return new ArrayList<>();
    }

    if (file.isDirectory()) {
        return findClassesInSourceRoot(classLoader,predicate);
    } else if (!file.getName().endsWith(".jar")) {
        return new ArrayList<>();
    }

    final List<Class<?>> classes = new ArrayList<>();

    try {

        final URL jar = file.toURI().toURL();

        final List<String> matches = new ArrayList<>();

        try (final JarInputStream stream = new JarInputStream(
                jar.openStream()); final urlclassloader loader = new urlclassloader(new URL[]{jar},classLoader)
        ) {
            JarEntry entry;
            while ((entry = stream.getNextJarEntry()) != null) {
                final String name = entry.getName();
                if (name == null || name.isEmpty() || !name.endsWith(".class")) {
                    continue;
                }

                matches.add(name.substring(0,name.lastIndexOf('.')).replace('/','.'));
            }

            for (final String match : matches) {
                try {
                    final Class<?> loaded = loader.loadClass(match);
                    if (predicate.test(loaded)) {
                        classes.add(loaded);
                    }
                } catch (final NoClassDefFoundError ignored) {
                }
            }
        }
    } catch (IOException | ClassNotFoundException e) {
        e.printstacktrace();
    }

    return ImmutableList.copyOf(classes);
}

private List<Class<?>> findClassesInSourceRoot(
        @NonNull final ClassLoader classLoader,@NonNull final File sourceRoot,@NonNull final Predicate<Class<?>> predicate
) {
    File[] files = sourceRoot.listFiles();

    if (files == null) return new ArrayList<>();

    ArrayList<Class<?>> classes = new ArrayList<>();

    List<String> classNames = getClassNames("",sourceRoot,sourceRoot);
    try {
        urlclassloader loader = new urlclassloader(new URL[]{sourceRoot.toURI().toURL()},classLoader);

        for (String className : classNames) {
            try {
                Class<?> aClass = loader.loadClass(className);
                if (predicate.test(aClass)) {
                    classes.add(aClass);
                }
            } catch (ClassNotFoundException ignored) {
            }
        }
    } catch (MalformedURLException e) {
        e.printstacktrace();
    }

    return classes;
}

private List<String> getClassNames(String basePath,File sourceRoot,File file) {

    ArrayList<String> classNames = new ArrayList<>();
    if (file.isFile() && file.getName().endsWith(".class")) {
        classNames.add(basePath + file.getName().replace(".class",""));
    } else if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null) {
            for (File subFile : files) {
                classNames.addAll(getClassNames(file.equals(sourceRoot) ? "" : basePath + file.getName() + ".",subFile));
            }
        }
    }

    return classNames;
}

}

我使用的方法

    private void loadModes() {

    File file = new File("plugins/MyPlugin/TheFolderWhereTheAddonsAreIn");

    if(!file.exists())
        file.mkdirs();

    addFromDir(file);
    addFromDir(new File("plugins")); //to check the plugins folder if there is an addon as a plugin

    for(Class<? extends SpectateMode> spectateMode : listedSpectateModes) {
        if(spectateMode != null) {
            //spectateMode.onEnable(); //not possible to enter
            Bukkit.getLogger().log(Level.CONfig,spectateMode.getName() + " loaded");
        }
    }

}

private void addFromDir(File dir) {
    SPClassLoader loader = new SPClassLoader();

    Arrays.stream(Objects.requireNonNull(dir.listFiles())).forEach(jar -> {
        if(jar.getName().endsWith(".jar")) {
            if(!loader.findClasses(instance.getClassLoader(),jar,SpectateMode.class).isEmpty()) {
                listedSpectateModes.addAll(loader.findClasses(instance.getClassLoader(),SpectateMode.class));
            }
        }
    });
}

SpectateMode类:

public abstract class SpectateMode {

/**
 * Do something when the SpectateMode get registered
 * For example registering an EventListener
 */
public abstract void onEnable();

/**
 * Returns the name of the SpectateMode
 *
 * @return the name of the SpectateMode
 */
public abstract String getName();

/**
 * Gets executed every Tick when a player has equipped this mode
 */
public abstract void execute(spectator spectator);
}

期待一个肯定的答案。

问候。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)