Cannot distinguish class "X" from class "Y", although X extends Y?

For some reason, trying to make class X another class Y in the third class Z raises a ClassCastException . This seems wrong to me, since class X extends another class Y Is there any specific reason why the class X cannot be added to Y , although X extends it?

See the following code for reference:

Y :

 public abstract class Y { /** * Called when the extension is enabled. */ public void onEnable() { } } 

X :

 public class X extends Y { @Override public void onEnable() { // Extension specific code. } } 

Z : (This code is the code that ClassCastException starts ClassCastException .)

 public class Z { private boolean loadExtension(ExtensionDescription description) { try { URLClassLoader loader = new ExtensionClassLoader(new URL[]{description.getFile().toURI().toURL()}); Y y = (Y) loader.loadClass(description.getMain()).newInstance(); } catch (Throwable t) {} } } 

If you know that loader.loadClass(description.getMain()).newInstance(); creates a new instance of X , then why does clicking ClassCastException Y ClassCastException a ClassCastException ?

+6
source share
1 answer

To illustrate further, here is an example:

Create a custom ClassLoader , for example. below (copied from here )

 package com.dd; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class CustomClassLoader extends ClassLoader { /** * The HashMap where the classes will be cached */ private Map<String, Class<?>> classes = new HashMap<String, Class<?>>(); @Override public String toString() { return CustomClassLoader.class.getName(); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { if (classes.containsKey(name)) { return classes.get(name); } byte[] classData; try { classData = loadClassData(name); } catch (IOException e) { throw new ClassNotFoundException("Class [" + name + "] could not be found", e); } Class<?> c = defineClass(name, classData, 0, classData.length); resolveClass(c); classes.put(name, c); return c; } /** * Load the class file into byte array * * @param name * The name of the class eg com.codeslices.test.TestClass} * @return The class file as byte array * @throws IOException */ private byte[] loadClassData(String name) throws IOException { BufferedInputStream in = new BufferedInputStream( ClassLoader.getSystemResourceAsStream(name.replace(".", "/") + ".class")); ByteArrayOutputStream out = new ByteArrayOutputStream(); int i; while ((i = in.read()) != -1) { out.write(i); } in.close(); byte[] classData = out.toByteArray(); out.close(); return classData; } } 

And here is the class Z

 package com.dd; import java.lang.reflect.InvocationTargetException; public class Z { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { CustomClassLoader loader = new CustomClassLoader(); Class<?> c1 = loader.findClass("com.dd.X"); System.out.println("Classloader:: "+ X.class.getClassLoader()); System.out.println("Classloader:: "+ loader.findClass("com.dd.X").getClassLoader()); X x = (X)c1.newInstance(); } } 

And here is the conclusion:

 Classloader:: sun.misc.Launcher$AppClassLoader@781fb069 Classloader:: com.dd.CustomClassLoader Exception in thread "main" java.lang.ClassCastException: com.dd.X cannot be cast to com.dd.X at com.dd.Z.main(Z.java:18) 
+4
source

All Articles