• JVM之类加载器上篇


    首先我们先看一个示例程序:

    package com.tfdd.test;
    
    /**
     * @desc 类加载校验
     * @author chenqm 
     * @date 2016年2月2日
     */
    class Singleton{
        private static Singleton singleton = new Singleton();
        public static int count1 ;
        public static int count2 = 0;
        
        private Singleton(){
            count1++;
            count2++;
        }
    
        public static Singleton getInstance(){
            
            return singleton;
        }
        
    }
    public class SingletonTest {
        public static void main(String[] args) {
            Singleton singleton = Singleton.getInstance();
            System.out.println(singleton.count1);
            System.out.println(singleton.count2);
        }
    }

    猜猜输出的结果是什么?据说80%的java程序猿都会犯的错误!

    1
    0

    就是这样一个结果,我们先不说为什么。接着讲我们的类加载器.

    类的加载大致分为三个部分:加载,连接,初始化。

    加载:查找并加载类的二进制数据

    连接:1.验证(确保被加载类的准确性) 2.准备(为类的静态变量分配内存,并将其初始化为默认值) 3.解析(将类中的符号引用转化为直接引用)

    初始化:为类的静态变量赋予正确的初始值(即赋上我们给出的值)

    然后我们再看看java程序对类的使用方式:主动使用和被动使用。请注意下面我说的这句话

    所有的JAVA虚拟机实现必须在每个类或接口被JAVA程序“首次主动使用”时才初始化他们。

    那么什么叫主动使用?基本上分为6种情况:

    --创建类的实例

    --访问某个类或接口的静态变量,或者对该静态变量赋值

    --调用类的静态方法

    --反射

    --初始化一个类的子类

    --java虚拟机启动时被标明为启动类的类

    了解了这些知识之后,我现在来回答之前的问题,

    Singleton.getInstance(); 调用了类的静态方法,符合首次主动使用该类的情况!那么我们进入初始化阶段。
    初始化已经属于类加载的第三步了,在第二步的连接的准备部分,已经赋过一次默认值了。所以应该是这样一个过程:
    1.singleton = null;count1=0;count2=0

    2.singleton = new Singleton(); 此时执行构造函数,结果为count1=1;count2=1
    3.count1没有被我们赋值跳过初始化,count2赋值为0所以结果为count1=1;count2=0
    (*注意) 类的静态变量赋值的顺序是按照代码的书写的顺序执行的。
    修改代码如下:
    package com.tfdd.test;
    
    /**
     * @desc 类加载校验
     * @author chenqm 
     * @date 2016年2月2日
     */
    class Singleton{
        public static int count1 ;
        public static int count2 = 0;
        private static Singleton singleton = new Singleton();
    
        private Singleton(){
            count1++;
            count2++;
        }
    
        public static Singleton getInstance(){
            
            return singleton;
        }
        
    }
    public class SingletonTest {
        public static void main(String[] args) {
            Singleton singleton = Singleton.getInstance();
            System.out.println(singleton.count1);
            System.out.println(singleton.count2);
        }
    }

    输出结果为

    1

    1

    证明赋值的顺序是根据代码书写的先后顺序执行的!




  • 相关阅读:
    如何快速定位到DBGrid的某一行!!!急...
    说说设计模式~单件模式(Singleton)
    EF架构~终于自己架构了一个相对完整的EF方案
    .Net——实现IConfigurationSectionHandler接口定义处理程序处理自定义节点
    在LINQ中实现多条件联合主键LEFT JOIN
    从LINQ开始之LINQ to Objects(上)
    WPF控件模板和数据模板
    WPF的ListView控件自定义布局用法实例
    初步探讨WPF的ListView控件(涉及模板、查找子控件)
    LINQ技巧:如何通过多次调用GroupBy实现分组嵌套
  • 原文地址:https://www.cnblogs.com/think-in-java/p/5178383.html
Copyright © 2020-2023  润新知