2016-04-30 65 views
-1

我收到了一个看似没有理由的ClassCastException。让我解释一下我的代码的结构: AbilityModifier是一个抽象类 ProjectileModifier是延伸AbilityModifier NoGravity一个抽象类是延伸ProjectileModifierClassCastException没有理由?

AbilityModifier有,我用它来找到所有属性调整自定义类加载器的类。这样我没有手动注册它们。但是,要自动注册它们,我需要将它们转换并添加到列表中。当我施放它时,它抛出一个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] 
+3

请发布异常的堆栈跟踪并在您的代码中指出它出现的位置。 –

+0

您能否添加完整的异常消息? – tmarwen

+0

好的,给我一分钟 – ViperLordX

回答

1

问题是类NoGravity是通过与您在代码中引用的类不同的类加载器加载的。因此,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)加载。

-4

Just Build->清理你的项目。

+0

你是什么意思,清理我的项目? – ViperLordX

+0

如何清理项目有助于解决ClassCastException?这不是ClassNotFoundException,你可以期待这样的异常或项目中缺少的库。 – Manish

+0

只需在android studio工具栏中创建选项,然后尝试清理然后重新编译然后运行你的项目 – bebo

0

因为C是A的一个间接子类,在这种情况下为AbilityModifier的NoGravity,所以NoGravity的每个实例都是AbilityModifier的一个实例。但是,clazz.newInstance()方法返回必须流传的Object。我建议你尝试将其铸造NoGravity,这样以后分配AbilityModifier这个对象:

AbilityModifier a = (NoGravity) clazz.newInstance();

编辑,你可以尝试其他的事情是这样的:

if (AbilityModifier.class.isAssignableFrom(clazz)) { 
    AbilityModifier instance = ((Class<AbilityModifier>) clazz).newInstance(); 
} 

希望这有助于!

+0

稍微偏离主题,据我所知,你可以废弃整个isSubclass()方法,并用'AbilityModifier.class.isAssignableFrom(loadedClass) – Dico

相关问题