2016-04-30 123 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