有关Java虚拟机类加载机制相关的文章一搜一大把,笔者这儿也不必再赘述一遍了。笔者这儿捞出一道code题要各位大佬来把玩把玩,假定你一眼就看出了端倪,那么祝贺你,你可以下山了:
​
  public class StaticTest
  {
     public static void main(String[] args)
     {
         staticFunction();
     }

     static StaticTest st = new StaticTest();

     static
     {
         System.out.println("1");
     }

     {
         System.out.println("2");
     }

     StaticTest()
     {
         System.out.println("3");
         System.out.println("a="+a+",b="+b);
     }

     public static void staticFunction(){
         System.out.println("4");
     }

     int a=110;
     static int b =112;
  }
  问题:请问这段程序的输出是什么?一般关于这类问题,小伙伴们脑海中必定浮现出这样的常识点:

  Java中赋值次第:

  父类的静态变量赋值

  自身的静态变量赋值

  父类成员变量赋值和父类块赋值

  父类结构函数赋值

  自身成员变量赋值和自身块赋值

  自身结构函数赋值

  按照这个理论输出是什么呢?答案输出:1 4,这样正确嚒?必定不正确啦,(midea808)这儿不是说上面的规矩不正确,而是说不能简略的套用这个规矩。 正确的答案是:

  2
  3
  a=110,b=0
  1
  4
  有没有答对呢?这儿首要的点之一:实例初始化不一定要在类初始化结束之后才开端初始化。 类的生命周期是:加载->验证->准备->解析->初始化->运用->卸载,只要在准备阶段和初始化阶段才会触及类变量的初始化和赋值,因此只针对这两个阶段进行剖析;

  类的准备阶段需求做是为类变量分配内存并设置默认值,因此类变量st为null、b为0;(需求留心的是假定类变量是final,编译时javac将会为value生成ConstantValue特征,在准备阶段虚拟机就会根据ConstantValue的设置将变量设置为指定的值,假定这儿这么定义:static final int b=112,那么在准备阶段b的值就是112,而不再是0了。)

  类的初始化阶段需求做的是施行类结构器(类结构器是编译器搜集悉数静态语句块和类变量的赋值语句按语句在源码中的次第吞并生成类结构器,政策的结构方法是(),类的结构方法是(),可以在仓库信息中看到),因此先施行第一条静态变量的赋值语句即st = new StaticTest (),此刻会进行政策的初始化,政策的初始化是先初始化成员变量再施行结构方法,因此打印2->设置a为110->施行结构方法(打印3,此刻a现已赋值为110,但是b仅仅设置了默认值0,并未结束赋值动作),等政策的初始化结束后持续施行之前的类结构器的语句,接下来就不具体说了,按照语句在源码中的次第施行即可。

  这儿面还牵涉到一个冷常识,就是在嵌套初始化时有一个特别的逻辑。特别是内嵌的这个变量恰好是个静态成员,(grandwaycanada)并且是本类的实例。 这会导致一个诙谐的现象:“实例初始化居然出现在静态初始化之前”。 其实并没有提早,你要知道java记载初始化与否的时机。看一个简化的代码,把关键问题说明清楚:

  public class Test {
     public static void main(String[] args) {
         func();
     }
     static Test st = new Test();
     static void func(){}
  }
  根据上面的代码,有以下进程:

  首先在施行此段代码时,首先由main方法的调用触发静态初始化。

  在初始化Test 类的静态部分时,遇到st这个成员。

  但恰巧这个变量引证的是本类的实例。

  那么问题来了,此刻静态初始化进程还没结束就要初始化实例部分了。是这样么?

  从人的角度是的。但从java的角度,一旦开端初始化静态部分,不论是否结束,后续都不会再从头触发静态初始化流程了。

  因此在实例化st变量时,实际上是把实例初始化嵌入到了静态初始化流程中,并且在楼主的问题中,嵌入到了静态初始化的开端方位。这就导致了实例初始化完全至于静态初始化之前。这也是导致a有值b没值的原因。

  毕竟再考虑到文本次第,效果就清楚明了了。

  具体看到这儿,心中大概有个结论了吧。

很多人都会做错的一道JVM题?【分享】的更多相关文章

  1. 大部分人都会做错的经典JS闭包面试题

    由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧. 先看题目代码: function fun(n,o) ...

  2. 关于ftp的学习:ftp很多人都会用。但会用,不代表我们真正了解它。

    ftp.sftp.ftps,您是否是也跟我一样搞不清楚他们的真正意义.它们之间有关联吗(究竟是何种关联),有区别吗(区别倒地在哪里). 亦或是以为自己知道它们,可我们真的了解并认识它们了吗? 如果您被 ...

  3. 这道js面试题号称99%的人会做错

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. 一道简单的 Java 笔试题,但值得很多人反思!

    前言 面试别人,对我来说是一件新奇事,以前都是别人面试我.我清楚地知道,我在的地域与公司,难以吸引到中国的一流软件人才.所以,我特地调低了期望,很少问什么深入的技术问题,只问一些广泛的.基础的.我只要 ...

  5. 这道面试必问的JVM面试题70%的Java程序员会做错

    前言 聊聊JVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别. JVM可以说和我们是老朋友了 ...

  6. 神贴真开眼界:为什么很多人倡导重视能力和素质,但同时对学历有严格要求?——代表了上一场比赛的输赢,招聘成本很重要。如果上一场游戏失败了,尽量让自己成为当前群体的尖子。学历只是其中的一个作品而已,但学历代表了学生时代为之做出的牺牲。人群自有偏向集中性 good

    对于软件工程师职位,没学历没关系,如果真觉得自己才高八斗,请在简历里附上 github项目链接或者 appstore/google play上你的作品.如果学历比别人低,那么想必是把时间和精力用在了其 ...

  7. 为什么很多人坚信“富贵险中求”?

    之家哥 2017-11-15 09:12:31 微信QQ微博 下载APP 摘要 网贷之家小编根据舆情频道的相关数据,精心整理的关于<为什么很多人坚信"富贵险中求"?>的 ...

  8. 我来科普一下为毛很多人升级了20M的电信光纤宽带反而感觉速度更卡了

    下载(在线看视频,看网页,下载游戏这类都是属于下载类应用) 为毛很多人升级20M光纤更慢了呢? 因为电信对你的上传速度做了手脚, 8M以及以上家用光纤宽带全部上传限速到100KB/s  也就是1M带宽 ...

  9. (转)Groupon前传:从10个月的失败作品修改,1个月找到成功 并不挶泥在这个点子上面,它反而往后站一步,看看他们已经做好的这个网站,可以再怎么包装成另一个完完全全不同的网站?所有的人所做的每件失败的事情中, 一定有碰到或含有成功的答案」在里面,只是他们不知道而已。 人不怕失败」,只怕宣布失败」

    (转)Groupon前传:从10个月的失败作品修改,1个月找到成功 今天读到 一个非常励志人心的故事 ,就像现在「叶问」有「前传」,最近很火红的团集购网站Groupon 也出现了「Groupon前传」 ...

随机推荐

  1. go 创建自己的区块

    package main import ( "time" "crypto/sha256" "bytes" ) //区块体 type Bloc ...

  2. SSM 实现登录注册功能

    1.上一篇SSM框架搭建好了之后就要开始写功能了,现在来写一个简单的登录注册功能 这几个包是自己手动创建的,然后往里面写代码 2.代码详情 package com.maike.controller; ...

  3. java非四舍五入

    Double htert=34.9768; DecimalFormat df = new DecimalFormat("#.00");// 保留五位小数非四舍五入型 df.setR ...

  4. 基于socketserver实现并发的socket编程

    目录 一.基于TCP协议 1.1 server类 1.2 request类 1.3 继承关系 1.4 服务端 1.5 客户端 1.6 客户端1 二.基于UDP协议 2.1 服务端 2.2 客户端 2. ...

  5. 如何创建Azure Face API和计算机视觉Computer Vision API

    在人工智能技术飞速发展的当前,利用技术手段实现人脸识别.图片识别已经不是什么难事.目前,百度.微软等云计算厂商均推出了人脸识别和计算机视觉的API,其优势在于不需要搭建本地环境,只需要通过网络交互,就 ...

  6. Python爬虫教程-使用chardet

    Spider-03-使用chardet继续学习python爬虫,我们经常出现解码问题,因为所有的页面编码都不统一,我们使用chardet检测页面的编码,尽可能的减少编码问题的出现 网页编码问题解决使用 ...

  7. SynchronusQueue

    /** * 当向SynchronousQueue插入元素时,必须同时有个线程往外取 * SynchronousQueue是没有容量的,这是与其他的阻塞队列不同的地方 */ public class S ...

  8. WPF 解决多个TreeViewItem同时触发某事件的简单方法

    原理是: 因为是双击事件,也就是同时引发了选择事件,TreeViewItem的IsSelected为True.通过触发器设置某个属性为特殊值,然后在CS页面的双击事件方法内判断是否此值即可. xaml ...

  9. 聊一聊 bootstrap 的轮播图插件

    今天做工作的时候,轻车熟路的做完,又用到了bootstrap的轮播图,觉得有必要安利一下这个插件,如果你需要的轮播图.功能不需要太炫酷,那么bootstrap的插件是你的首要选择. 使用方式 引入js ...

  10. Pycharm新手使用教程(详解)

    Pycharm新手使用教程(详解) [注]: 如果想要下载Pycharm工具,直接去<开发工具>中进行下载. 简介 Jetbrains家族和Pycharm版本划分: pycharm是Jet ...