我正在阅读this文章,它说:
如果我们有两个由这些CustomClassLoader加载的Student类实例,例如student1和student2,那么student1和student2不是类型兼容的。换句话说,
学生3 =(学生)学生2;
将抛出ClassCastException,因为JVM将这两者视为独立的不同类类型,因为它们由不同的ClassLoader实例定义。
现在我明白了它想传达的内容:那就是如果我们通过使用两个不同的类加载器来加载相同的类,那么它们将不是类型兼容的。所以很好。
但它使用的例子让我感到困惑,即
学生3 =(学生)学生2;
当我们声明像 Student student 这样的引用变量时,编译器所寻找的是 Studnet 存在的所有内容在运行时,我们将这个引用变量分配给一个真正的加载类,我们用哪个类加载器加载所述类真的很重要吗?我怀疑,因为根据我的理解,只有当我们执行'new'或者我们在其上调用静态字段时才会使用类加载器,而不是在我们简单地声明它的类型时。
请在此澄清我,并帮助我纠正我在这方面的理解。
谢谢, Mawia
答案 0 :(得分:3)
这大多是正确的但是当分配发生时,JVM需要确保它是正确的。因此它检查:我可以将右侧(RHS)分配到左侧(LHS)。
规则说当你可以将RHS的运行时类型向下转换为LHS的类型时允许这样做。
所以在编译时,上面的代码看起来没问题。但是在运行时,调用isAssignableFrom()
返回false,因为这两种类型不同。
equals()
中的方法Class
返回true
,如果限定名称等于,>>当类加载器相同时。这就是为什么你在这种情况下获得ClassCastException
。
使用的方法是作为本机代码实现的,因此您无法看到正在发生的事情。但是,当两个类的类加载器相同时,方法isInstance()
和isAssignableFrom()
仅返回true。
答案 1 :(得分:1)
是的,在运行时,哪个类加载器确实加载了一个类真的很重要。每次必须加载类时都会检查类加载器。这不仅仅是遇到new
或静态字段时。每次在Java代码中出现类名时都会发生这种情况,或者更确切地说,在字节代码中引用类名并执行字节代码时会发生这种情况。