【发布时间】:2016-04-30 12:50:37
【问题描述】:
我似乎无缘无故地收到了 ClassCastException。让我解释一下我的代码结构: AbilityModifier 是一个抽象类 ProjectileModifier 是一个抽象类,它扩展了 AbilityModifier NoGravity 是一个扩展 ProjectileModifier 的类
AbilityModifier 有一个自定义 ClassLoader,我用它来查找所有能力修饰符。这样我就没有手动注册它们了。但是,要自动注册它们,我需要转换它们并将它们添加到列表中。当我施放它时,它会抛出一个 ClassCastException,说 redempt.divinity.ability.modifier.modifiers.NoGravity 不能施放为 redempt.divinity.ability。我做了一个测试,一切正常,没有例外:
package redempt.test;
public class Main {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Class<?> clazz = C.class;
Object o = clazz.newInstance();
A a = A.class.cast(o);
System.out.println("Finished!");
}
}
class A {
public A() {
}
}
class B extends A {
public B() {
}
}
class C extends B {
public C() {
}
}
所以这行得通,但由于某种原因,我的其他代码没有。让我给你所有涉及的课程:
能力修饰符:
package redempt.divinity.ability.modifier;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import redempt.divinity.Main;
import redempt.divinity.ability.AbilityType;
public abstract class AbilityModifier {
public static Set<AbilityModifier> modifiers = new HashSet<AbilityModifier>();
public abstract void onUse(Player player);
public abstract String getName();
public abstract Material getRepresentation();
public abstract AbilityType getType();
public static void registerAll() throws IOException, ClassNotFoundException, URISyntaxException, InstantiationException, IllegalAccessException {
File file = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI());
JarFile jar = new JarFile(file);
file.toURI().toURL();
URL[] urls = {file.toURI().toURL()};
List<String> names = new ArrayList<String>();
URLClassLoader loader = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName().replace("/", ".");
if (name.endsWith(".class")) {
try {
Class<?> clazz = loader.loadClass(name.replaceAll("\\.class$", ""));
System.out.println("Loading class: " + clazz.getSimpleName());
System.out.println(isSubclass(clazz));
if (isSubclass(clazz) && !Modifier.isAbstract(clazz.getModifiers())) {
names.add(clazz.getSimpleName());
AbilityModifier modifier = AbilityModifier.class.cast(clazz.newInstance());
}
} catch (NoClassDefFoundError e) {
System.out.println("Unable to load class: " + name);
}
}
}
loader.close();
jar.close();
System.out.println(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL().getPath());
System.out.println("All ability modifiers found:");
for (String name : names) {
System.out.println(name);
}
}
public static void register(Class<? extends AbilityModifier> clazz) {
}
private static boolean isSubclass(Class<?> clazz) {
if (clazz.getSuperclass().equals(Object.class)) {
return false;
}
return clazz.getSuperclass().getName().equals(AbilityModifier.class.getName()) ? true : isSubclass(clazz.getSuperclass());
}
}
ProjectileModifier:
package redempt.divinity.ability.modifier;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import redempt.divinity.ability.Ability;
public abstract class ProjectileModifier extends AbilityModifier {
public abstract void onUse(Player player, Entity projectile);
@Override
public void onUse(Player player) {
}
public abstract void onHit(Ability item, int level, EntityDamageByEntityEvent event);
public abstract void onTick(Entity projectile);
}
无重力:
package redempt.divinity.ability.modifier.modifiers;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.util.Vector;
import redempt.divinity.ability.Ability;
import redempt.divinity.ability.AbilityType;
import redempt.divinity.ability.modifier.ProjectileModifier;
public class NoGravity extends ProjectileModifier {
Vector vector;
Location lastpos;
@Override
public void onUse(Player player, Entity projectile) {
vector = player.getLocation().getDirection().normalize();
lastpos = projectile.getLocation().clone();
}
@Override
public String getName() {
return "No gravity";
}
@Override
public Material getRepresentation() {
return Material.FEATHER;
}
@Override
public AbilityType getType() {
return AbilityType.PROJECTILE;
}
@Override
public void onHit(Ability item, int level, EntityDamageByEntityEvent event) {
}
@Override
public void onTick(Entity entity) {
lastpos.add(vector);
if (lastpos.getBlock().getType().equals(Material.AIR)) {
entity.setVelocity(vector);
}
lastpos = entity.getLocation().clone();
}
public NoGravity() {
}
}
例外:
java.lang.ClassCastException: redempt.divinity.ability.modifier.modifiers.NoGravity cannot be cast to redempt.divinity.ability.modifier.AbilityModifier
at redempt.divinity.ability.modifier.AbilityModifier.registerAll(AbilityModifier.java:47) ~[?:?]
at redempt.divinity.Main.onEnable(Main.java:30) ~[?:?]
at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:292) ~[spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:340) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:405) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at org.bukkit.craftbukkit.v1_9_R1.CraftServer.loadPlugin(CraftServer.java:361) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at org.bukkit.craftbukkit.v1_9_R1.CraftServer.enablePlugins(CraftServer.java:321) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at net.minecraft.server.v1_9_R1.MinecraftServer.t(MinecraftServer.java:411) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at net.minecraft.server.v1_9_R1.MinecraftServer.l(MinecraftServer.java:376) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at net.minecraft.server.v1_9_R1.MinecraftServer.a(MinecraftServer.java:331) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at net.minecraft.server.v1_9_R1.DedicatedServer.init(DedicatedServer.java:269) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at net.minecraft.server.v1_9_R1.MinecraftServer.run(MinecraftServer.java:527) [spigot-1.9.jar:git-Spigot-f04e043-52c7fc0]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_65]
【问题讨论】:
-
请发布异常的堆栈跟踪并在您的代码中指出它发生的位置。
-
能否请您添加完整的异常消息?
-
好的,请稍等
-
@Manish 你错了。可以将子类转换为(其中一个)超类,这只是(通常)不必要的。问题更可能是类加载器之一,并且使用的
AbilityModifier类是由与NoGravity及其(大)父级AbilityModifier不同的类加载器加载的(因此AbilityModifier(!)有两个不同的类实例)。 -
@ViperLordX 这取决于加载了哪个类加载器
AbilityModifier。使用加载AbilityModifier的类加载器(例如AbilityModifier.class.getClassLoader())可能会更好。也就是说,我不经常使用类加载器,所以我可能有点偏离。