Java类的加载过程以及单例模式的简单解析

代码写了很多年了,一直有碌碌无为的感觉。相信很多工作三四年的人都会和我有一样的想法,觉得这样子的状态就是老油条的写照,但是却不知道其他的出路,总想打破现在的这个状态,但是不知道如何下手。但是,告诉你们,其实我也不知道该怎么下手。为了打破这个宁静,给自己找点事情做,于是,决定从基础再重新学习一遍,顺便带着我家的懒婆娘学习。
牛逼的人直接跳过,这是给那些一知半解的人看到的。我知道很多人一看,心里只有一个想法:这都是大家都知道的事情,类的加载无非就是几个过程。确实,如果都懂的人,请自行绕过,因为这确实很基础,为了突出这个不同的地方,所以我把单例模式的构建特点也一起分析。之前在华为外包面试的就被问到的一个问题就是单模式,当时并不知道其中的原理,因为我告诉面试官,不懂的就网上看,至于原理,确实不知道,于是,基于华为的狼性文化,不录用,吐槽一句:尼玛这是外包,搞的正式员工一样。
回到正题,Java虚拟机的类加载过程主要有七个步骤:Loading、verification、preparation、resolution、initialization、using、unloading。翻译中文就是:加载,验证,准备,解析,初始化,使用和卸载。具体的可以参考很早之前就有人写的博客:http://www.importnew.com/18548.html。这篇博文里面主要从使用方面讲解,JVM的加载很有必要知道,不然哪怕是堆栈溢出的异常都不知道怎么回事。
类的加载,首先会加载静态的东西:静态代码块,静态属性和静态方法,这些是全局的,但是静态的方法会初始化,但是不调用的话是不会执行的。静态变量,比如:
private static int temp=1;  
    类加载的时候,定义的是str = 0,只有初始化完成之后,才会给str复制1,而很多类似的静态是按照程序顺序进行加载的。初始化是JVM类加载的最后一步,静态的其实就是相当于C语言的全局变量,Java称之为类变量。静态变量是全局存在的,有点人直接new一个对象来引用静态变量,以为这样可以防止内存消耗的问题,其实是一样的,类引用和实例引用,只不过是一个亲自引用,一个是代言人去引用,结果都是把静态方法拉出放在程序里面。那么加载完静态的,那么初步的类加载就完成了,这特么说的也太简单了吧,其实大家可以去看看牛人说的具体机制,我水平有限,说错了就耽误大家了。接下来是不是该询问:非静态的方法,变量,以及代码块呢?这些,都是实例化的引用,如果你不new的话,代码块也是不会执行的,new 的时候,代码块是最先执行的,其次才是父类的构造方法,再次才是自身的构造方法,卸载销毁就刚好想法,儿子先挂,老子最后挂,因为将还是老的辣!
接下来就是进入主题了,单例模式的实现有饿汉式,懒汉式,具体的实现看我的上一篇博客,有介绍的。如果没有并发的编程,饿汉式是最简单粗暴的,还很容易记住。我开始就是使用饿汉式的,熟悉,但是多次的跳槽为了应付面试,还是要脑补懒汉式以及DCL机制等等。除了这几种,我主要是推荐的内部静态类实现单例模式,具体写法直接看代码:
public class Singleton {

    private Singleton() {
    }

    public static Singleton getSingleInstance() {
        return SingletonHolder.sInstance;
    }

    private static class SingletonHolder{
        private static Singleton sInstance = new Singleton();
    }
}
本人上篇博客其实已经有详细的说明,但是没有设计到类的加载,所以借这个机会就再次说明下单例模式,因为这个模式的使用范围实在是太广了额,很多面试官有特别喜欢问,当然,还要具备能够白板写出来的能力才行,不是看看就完了的。
那么就这基础的东西来分析一下,为什么DCL不能完全做到线程安全,而这个就可以呢。看上面对类的加载以及初始化的过程。静态的只会在类首次的时候加载一次,内部类其实可以看作是类的一个属性,所以可以轻松的访问外部类的属性和方法,在类第一次加载的时候,静态的内部类就一直在并且不会进行二次加载,注意一点,final修饰的常量,或者放在常量池里面的常量,是准备阶段就已经赋值了,对,没看错,是在初始化之前的准备阶段就已经有值了,所以常量显示的速度是很快的。实例化的时候,虚拟机才会加载SingletonHolder这个类,只有被调用的时候才会初始化sInstance,也做到了延时的功能,懒汉式的作用就是如此,但是高并发的环境下,即使是DCL还是会有问题。这样就实现了线程安全,并且知道为什么吧!最后说明一点,这篇博文重点是在说明类的加载这个很简单,仅仅是借助这个例子来说明而已,但是Android面试经常问到的问题。不要吐槽太简单,那是因为小伙伴们懂的实在是太多了!
如果有说错的地方,希望指出,一起交流,谢谢!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章