先说一下我的得出的结论 :
1. 在java中 当你用一个类加载器 去加载一个类的时候 这个类里面所有的出现的过得类 都会通过这个类加载器加载在这个类后续 的操作中,只要是有由这个类衍生出的 那么涉及的类 都由这个类加载器进行加载 该类加载器为默认加载器。
2. 每个类加载器(应该说是类加载器的实例) 后面对应的其实是一堆class元信息 一个类加载器(应该是实例)的后面的东西,是一个大的圈圈,从这个类加载器进去的类 这个类的实例 活动的 范围 就在这个 加载器的范围中,别的类加载器不认识你,不会识识别你,即使是同一个类。
3. 类通过类的命名空间,与加载自己的类加载器建立联系。
下面结合代码说一下:
首先我自定义了一个类加载器
public class FatherLoader extends ClassLoader{
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("============FatherLoader=============loadClass:"+name);
Class<?> c = findLoadedClass(name);
if (c == null) {
if (name.startsWith("java"))
return super.loadClass(name);
String path = checkCouldLoad(name);
if (path == null || "".equals(path))
return null;
else
return realLoad(path);
}
return c;
}
.....
}
然后定义了一下些基本的类
public class ShowInfo {
public void show(Entity en){
System.out.println( " method in");
Entity rnn=(Entity)en;
System.out.println(rnn.name);
}
}
public class Entity {
public String name="zy";
}
然后建立一个测试类 用自定义的类加载器去加载
public class LoaderTest {
static {
try {
Entity en=new Entity();
ShowInfo show = (ShowInfo) new FatherLoader().loadClass("com.laozhao.entity.show.ShowInfo").newInstance();
show.show(en);
/*
Method[] methods=shop.getClass().getDeclaredMethods();
for(Method itm: methods){
if(itm.getName().contains("show"))
{
itm.invoke(en);
}
}*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
然后使用main方法去调用
public static void main(String[] args) throws Exception {
new FatherLoader().loadClass("com.laozhao.loader.LoaderTest").newInstance();
}
然后就报错了
============FatherLoader=============loadClass:com.laozhao.loader.LoaderTest
============FatherLoader=============loadClass:java.lang.Object
============FatherLoader=============loadClass:java.lang.Throwable
============FatherLoader=============loadClass:java.lang.Exception
============FatherLoader=============loadClass:com.laozhao.entity.Entity
============FatherLoader=============loadClass:java.lang.System
============FatherLoader=============loadClass:java.lang.StringBuilder
============FatherLoader=============loadClass:java.lang.Class
============FatherLoader=============loadClass:java.io.PrintStream
en:com.laozhao.loader.FatherLoader
============FatherLoader=============loadClass:com.laozhao.loader.FatherLoader
============FatherLoader=============loadClass:java.lang.ClassLoader
============FatherLoader=============loadClass:java.lang.CharSequence
============FatherLoader=============loadClass:java.io.InputStream
============FatherLoader=============loadClass:java.io.FileInputStream
============FatherLoader=============loadClass:com.laozhao.entity.show.ShowInfo
============FatherLoader=============loadClass:java.lang.String
============FatherLoader=============loadClass:java.net.URL
============FatherLoader=============loadClass:java.io.File
============FatherLoader=============loadClass:java.lang.Object
============FatherLoader=============loadClass:com.laozhao.entity.show.ShowInfo
java.lang.ClassCastException: com.laozhao.entity.show.ShowInfo cannot be cast to com.laozhao.entity.show.ShowInfo
at com.laozhao.loader.LoaderTest.<clinit>(LoaderTest.java:18)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at com.laozhao.Main.main(Main.java:20)
结合打印的日志 可以看到 在使用FatherLoader记载并初始化LoaderTest的时候 所有相关的类也都通过FatherLoader进行了记载,仔细看报错信息,你会发现非常有趣java.lang.ClassCastException: com.laozhao.entity.show.ShowInfo cannot be cast to com.laozhao.entity.show.ShowInfo: ShowInfo不能强转为ShowInfo,除了强转我还试了反射,报的错和这个差不多,原因也很简单,那是:
ShowInfo show = (ShowInfo) new FatherLoader().loadClass("com.laozhao.entity.show.ShowInfo").newInstance();
在这行代码中 = 左边的类和右边的类尽管来自同一个class文件 是由不同的类加载器实例加载的 彼此是隔离的 不认识,所以无法强转,报的错也贼有意思。
换成下面这样就可以了:
ShowInfo show = (ShowInfo) LoaderTest.class.getClassLoader().loadClass("com.laozhao.entity.show.ShowInfo").newInstance();
这样就保证同一个类加载器实例了或者直接这样:
ShowInfo show=new ShowInfo();
使用new关键字 自动使用默认的类加载器 也就是加载LoaderTest的加载器