有关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. fis3打包中的一些注意事项

    1.在html文件中,如果在标签的style属性内添加路径,fis不会识别改路径并打包,如 2.fis主要针对静态文件进行打包.对其他文件打包会出现一些问题. 比如jsp页面.下面的例子script. ...

  2. Linux 命名管道

    前文中笔者介绍了管道,本文接着介绍命名管道.文中演示所用环境为 Ubuntu 18.04 desktop. 命名管道(named pipe)又被称为先进先出队列(FIFO),是一种特殊的管道,存在于文 ...

  3. linux服务器上配置进行kaggle比赛的深度学习tensorflow keras环境详细教程

    本文首发于个人博客https://kezunlin.me/post/6b505d27/,欢迎阅读最新内容! full guide tutorial to install and configure d ...

  4. Java设计模式:Singleton(单例)模式

    概念定义 Singleton(单例)模式是指在程序运行期间, 某些类只实例化一次,创建一个全局唯一对象.因此,单例类只能有一个实例,且必须自己创建自己的这个唯一实例,并对外提供访问该实例的方式. 单例 ...

  5. oracle自定义函数:将使用点分隔符的编码转成层级码格式的编码

    维护一个旧的系统,表设计中只有编码,而没有其他排序相关的字段,然后根据编码排序出现了顺序错乱的问题. 详细地说,其编码设计是使用[.]分隔符的编码,比如1.1.1.1.1.1.1.1.1.2这样的格式 ...

  6. Mac 应用程序不能打开解决方法

    Mac 应用程序不能打开解决方法 关键是 文件原本是可执行文件,由于权限丢失,才变成了类型不明的文件,导致软件无法打开. 参考: https://www.macbl.com/article/tips/ ...

  7. WebSocket数据加密——AES与RSA混合加密

    前言 之前在写“一套简单的web即时通讯”,写到第三版的时候没什么思路,正好微信公众号看到一篇讲API交互加密,于是就自己搞了一套AES与RSA混合加密,无意中产生应用在WebSocket想法,好在思 ...

  8. 前端之photoshop的简单使用

    常用图片格式 图片是网页制作中很重要的素材,图片有不同的格式,每种格式都有自己的特性,了解这些特效,可以方便我们在制作网页时选取适合的图片格式. 图片格式及特性如下: 1.psd psd是photos ...

  9. C#函数的参数传递2(ref\out)

    using System; namespace class1 { class program { static void Main(string[] args) { Console.Write(&qu ...

  10. SQL SERVER 数据库授权指定用户

    在查询分析器下运行以下语句即可: GO USE [master] GO ALTER AUTHORIZATION ON DATABASE::[数据库名] TO [用户名] GO