2016-04-30 4 views
-1

Я получаю исключение ClassCastException, по-видимому, без причины. Позвольте мне объяснить структуру моего кода: AbilityModifier является абстрактным классом ProjectileModifier является абстрактным классом, который расширяет AbilityModifier NoGravity класс, который расширяет ProjectileModifierClassCastException без причины?

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() { 

    } 
} 

так, что работает, но по какой-то причине, мой другой код не делает. Позвольте мне дать вам все классы, связанные:

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

Пожалуйста, разместите stacktrace исключения и укажите в коде, где это происходит. –

+0

Не могли бы вы добавить полное сообщение об исключении? – tmarwen

+0

Конечно, дайте мне минуту – ViperLordX

ответ

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).

-4

Just Build-> Очистите свой проект.

+0

Что вы хотите, очистить мой проект? – ViperLordX

+0

Как очистка проекта поможет в разрешении ClassCastException? Это не ClassNotFoundException, где вы можете ожидать таких аномалий или недостающих библиотек в проекте. – Manish

+0

просто перейдите к варианту сборки на панели инструментов студии android и попробуйте очистить, а затем восстановить d, а затем запустите проект – bebo

0

Поскольку C является косвенным подклассом A, в этом случае NoGravity of AbilityModifier, каждый экземпляр NoGravity является экземпляром AbilityModifier. Однако метод clazz.newInstance() возвращает объект, который должен быть запущен. Я предлагаю вам попробовать назначить AbilityModifier этого объект после приведения его в NoGravity, как это:

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

EDIT, еще одна вещи, вы можете попробовать следующую:

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

Надеется, что это помогает!

+0

Немного от темы, насколько я знаю, вы можете отказаться от всего своего метода isSubclass() и заменить его на 'AbilityModifier.class.isAssignableFrom (loadClass);' – Dico

Смежные вопросы