问题描述
我目前正在开发一个插件,希望在其中创建插件。 因此,我使用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 (将#修改为@)