我因为看似没有理由而得到ClassCastException。让我解释一下我的代码结构: AbilityModifier是一个抽象类 ProjectileModifier是一个扩展AbilityModifier的抽象类 NoGravity是一个扩展ProjectileModifier
的类AbilityModifier有一个自定义的ClassLoader,我用它来查找所有的能力修饰符。这样我就不会手动注册它们。但是,要自动注册它们,我需要转换它们并将它们添加到List中。当我转换它时,它抛出一个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() {
}
}
这样可行,但出于某种原因,我的其他代码却没有。让我告诉你所涉及的所有课程:
AbilityModifier:
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);
}
NoGravity:
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]
答案 0 :(得分:1)
问题是,类NoGravity
是通过与您在代码中引用的AbilityModifier
类不同的类加载器加载的。因此,NoGravity
有一个不同的AbilityModifier
类实例作为其祖父母,因此投射不会起作用。
要解决此问题,您需要使用与在代码中加载AbilityModifier
的类加载器相同的类加载器。
您需要更改:
URLClassLoader loader = URLClassLoader.newInstance(urls,
ClassLoader.getSystemClassLoader());
要
URLClassLoader loader = URLClassLoader.newInstance(urls,
AbilityModifier.class.getClassLoader());
有关详细信息,请参阅Understanding Java class loading:
在运行时,Java类由该对唯一标识 - 类的完全限定名称和加载它的定义加载器。如果两个不同的加载器定义了相同的命名(即相同的完全限定名称)类,则这些类是不同的 - 即使.class字节相同并从同一位置(URL)加载。
答案 1 :(得分:0)
由于C是A的间接子类,在本例中是AbilityModifier的NoGravity,NoGravity的每个实例都是AbilityModifier的一个实例。但是,clazz.newInstance()方法返回必须进行转换的Object。我建议您在将此对象转换为NoGravity之后尝试为此对象分配,如下所示:
$(function(){
$('.fadeIn img:gt(0)').hide();
// assign this to a variable, since we're going to check it often
var total = $('.fadeIn img').length;
// initialize the counter
// You can adjust this number as desired.
// For example, set it to 0 if you want the show to end on the first slide
var count = 1;
// assign the interval to a variable so we can clear it
var slideInterval = setInterval(function() {
// if the current slide count is equal to or greater than the total slides, clear the interval
if (++count >= total) {
// stops the slideInterval (and therefore the slideshow)
clearInterval(slideInterval);
// You could do other things here if desired....
}
$('.fadeIn :first-child').fadeOut()
.next('img').fadeIn()
.end().appendTo('.fadeIn');},
2000);
});
编辑,你可以尝试的另一件事是:
AbilityModifier a = (NoGravity) clazz.newInstance();
希望这有帮助!
答案 2 :(得分:-4)
Just Build-&gt;清理你的项目。