虚拟机加载类的途径:
1、Dog dog = new Dog();
这个动作会导致常量池的解析,Dog类被隐式装载。
如果当前ClassLoader无法找到Dog,则抛出NoClassDefFoundError。
2、Class clazz = Class.forName(“Dog”);
Object dog =clazz.newInstance();
通过反射加载类型,并创建对象实例
如果无法找到Dog,则抛出ClassNotFoundException。
3、Class clazz = classLoader.loadClass(“Dog”);
Object dog =clazz.newInstance();
通过反射加载类型,并创建对象实例
如果无法找到Dog,则抛出ClassNotFoundException。
那么,1和2和3究竟有什么区别呢?分别用于什么情况呢?
1和2使用的类加载器是相同的,都是当前类加载器。(即:this.getClass.getClassLoader)。
3由用户指定类加载器。
如果需要在当前类路径以外寻找类,则只能采用第3种方式。第3种方式加载的类与当前类分属不同的命名空间。
当前类加载器命名空间对其不可见。当然,如果被加载类的超类对于当前类命名空间可见的话,则可以进行强制转型。
第1和第2种情况区别不大。如果,Dog类在编译时无法得到,则使用第2种方式。
另外,第1种和第2种都会导致类被初始化,即:执行类的静态初始化语句,而第3种情况不会。
另外注意,第1种抛出Error,第2、3种抛出Exception,它们分属于不同的异常/错误分支。
-----------------------------
对象实例化方式:
1、new Dog();
2、clazz.newInstance();或者clazz.getConstructor(...).newInstance(...);
3、Object.clone();//通过本地方法进行复制
4、反序列化